CPP Not Defteri

2020-07-26 |

C++ Defteri

cs204 dersi boyunca notlar.

Konular

Temeller

Preprocessor compiler linker

linker obj file'ları ve kütüphaneleri alıp hepsini birleştiriyor. compiler tamamen cpp'da. cpp'ı bilgisayarın anlayacağı şekle çeviriyor.

Preproccessor - translation unit - include da fark var "" => proje dosyası kontrol edilir - <> = standart kütüphaneye bakılır - #define ___ ____ => identifier, token-string - tüm tanımlamalar compilation dan önce değiştirilir. - const double PI = 3.1416 vs #define PI 3.14 - const olan daha iyi çünkü debug sürecinde ne olduğunu anlayabiliriz diğerinde otomatik üzerine yazılıyor.

Conditional Preprocessing

#ifdef __ => identifier =====> if defined
*statements*
#endif

#ifndef ======> if not defined

#undef => define'ı kaldırmaya yarıyor

# => bunlarla beraber

Macros

#define MULTIPLY(a,b) a*b
#define SQUARE(x) x*x

kullanırken dikkatli olunması gerekiliyor. #define SQUARE(x) x*x int x = SQUARE(3+5); =OUTPUT= 3+5*3+5

g++ İle Preprocess İşlemleri g++ -E test.cpp dış programdaki kodlar buraya dahil edilir.

g++ -S test.cpp assemble edilerek bir assembly dosyası oluşturulur.

g++ -C test.cpp compile edilmiş kodu oluşuturıur

gcc main.c -o main Use option -o, as shown below, to specify the output file name for the executable.

gcc -Dname[=value]

Veri Tipi Boyutları

Type Typical Bit Width Typical Range
char 1byte -127 to 127 or 0 to 255
unsigned char 1byte 0 to 255
signed char 1byte -127 to 127
int 4bytes -2147483648 to 2147483647
unsigned int 4bytes 0 to 4294967295
signed int 4bytes -2147483648 to 2147483647
short int 2bytes -32768 to 32767
unsigned short int 2bytes 0 to 65,535
signed short int 2bytes -32768 to 32767
long int 8bytes -2,147,483,648 to 2,147,483,647
signed long int 8bytes same as long int
unsigned long int 8bytes 0 to 4,294,967,295
long long int 8bytes -(2^63) to (2^63)-1
float 4bytes
double 8bytes
long double 12bytes
wchar_t 2 or 4 bytes 1 wide character

Pointerlar

Pointers => A pointer is variable to stora an "address in computer memory" It points to a memory location

* => follow the address go to object with address

& => get the address go to addresss with object

Pointer Tanımlama

int *ptr;
char *pchar;
ptr = &counter; // Store value in it;
cout << *ptr; // Dereference try to reach the value the pointer points to
cout << (*ptr).Day(); 
cout << ptr->Day(); // Diğeri ile aynı işlemi yapıyor.

char *p;

char * = NULL;

**Null Pointers **

char * = NULL;

NULL is replaced by nullptr in C++09;

Dereferencing (*)

Pointerlardaki değere erişip değiştirme yapmak istersen deferencing kullanabiliriz. Bunun için

    int *asd;
    std::cout << *asd << endl;  

Static memory allocation ==> int array[100] If memory allocated at runtime on the fly we need dynamic memory allocation

Dynamic Memory Allocation

*new type*

double *p; // a pointer for double

p = new double; // Memory allocated for double value

veya p2 = new int[4] => it gives dynamic memory

cin >> no_students;
Student* students = new Student[no_student];
Student s1,s2;
students[0] = s1;
students[1] = s2;
int* primenumveber = new int [100];
primenumbers[0] = 2;
primenumbers[1] = 3;
int *pa = new int[100];
//pa[0] and *pa aynı şey
// pa[1] == *(pa+1) ===> true
//+1 4byte ilerle demek

Pointer Arithmetic

Pointer aritmatiğinide önemli olan kullandığımız veri tipinin size'dır.

int myArray[100];
int* p1 = &(myArray[5]);
int* p2 = &(myArray[10]);
cout << p1 << " " << p2 << endl;

int const p => CONSTANT pointer to an int const int p => pointer to a CONSTANT int

Heap ve Stack

  • Memory linear bir yapı olarak düşünülebilir.

Stack - Automatic variable'lar burada saklanıyor Heap - Programda en büyük segmente sahip olan yer - new'ler her zaman heapten geliyor

  • Stack adresleri düşerken heap adresleri yükselir. tüketme yapıları birbirlerinden farklı
int s = 0;
cout << &s << endl; // Bu stackten geliyor 0x00010
int k = 2;
cout << &k << endl; // Bu stackten geliyor 0x00008 adres daha küçük

int *p = new int;
cout << &p << endl; // Pointer'ın adresi stackten geliyor
cout << p << endl; // Pointer'ın sakladığı adres HEAP
  • global ve static değişkenler farklı bir segmentten çağrılıyor. stack veya heapde değiller
  • bunun detaylarına şu siteden ulaşılabilir https://stackoverflow.com/questions/93039/where-are-static-variables-stored-in-c-and-c

Basic Data Structures

Linked Data Structures

Arrays - Çok fazla veya az memory ayrılmış olabilir. yer ayırma problemi var - Kullanım kolaylığı var. - Doğrudan erişim imkanı, indeksler ile ulaşabiliyoruz. - Sıralanmış bir diziye bir öğe eklemek, tüm öğelerin kaydırılmasını gerektirebilir.

Vectors - Yeniden boyutlandırılabilir ancak verimsiz. - tüm elemanların kaydırılması gerektirir.

Linked List

  • Ekleme silme daha kolay
  • Bir elemana ulaşabilmek için tüm listede dolaşmak gerekebilir.
  • head, tail
struct node{
    string word;
    int num;
    node *next;
};
node *p = new node;
struct point{
    int x;
    int y;

    // Default constructor
    point::point(){
        x=0;
        y=0;
    }

    // Constructor
    point::point(int x_cord, y_cord) {
        x = x_cord;
        y = y_cord;
    }
}

Yeni bir node ekleme

    node *p, *q;
    p = new node(5,"Ali",nullptr);

    node *q;
    q = new node(6,"Musa",nullptr);

    p->next = q;

Linked listte dolaşma

Bunun için bir walk değişkeni oluşturulup liste üzerinde gezilir.

node* walk = head;
while(pt){
    cout << ptr -> info << endl;
    ptr = ptr->next;
}
//nullptr olana kadar dönene kadar gidiyor

Listenin sonun ekleme

void Add2End(node * tail, int id){
    node *nn = new node(id,nullptr);
    tail->next = nn;
}

Static vs Dynamic Memory Allocation

  • Memory allocated during compile time is called static memory
  • Static memory => boyut sabit kalır
int main(){
    int arr[5] = {1,2,3,4,5}; // Bu statik bir değişken
 }

Problemler 1. Program sırasında boyutu arttıramıyoruz 2. Eğer az verilirse memory boşa gider 3. Eğer fazladan veri giderse program patlar

Dynamic Memory Allocation - Run-time'da memory allocation yapılabiliyor - Allocate edilen memory'e sadece pointerlar ile ulaşabilir. - Bundan dolayı pointerları kaybetmemek gerekiyor - Heap'ten allocation yapılıyor.

Automatic Variables - C++ allocates memory oh the stack - Scope'u kadar yaşarlar ondan sonra silinir

Programmer delete to release space when it is no longer needed.

Silinene kadar her zaman oradalar - local variables = { } süslü parentezler kapanınca ömrü biter - global variables = programın tüm hepsi için geçerlidir - static variables = global gibi program bitince silinir. - Pointers delete delete pointerVariable

Stack

Kullanıldığı Yerler

  • Stack memory
  • Local variables
  • Recursion (stack overflow)

Özellikler

  • Stack temel veri yapılarından birisidir. Stack LIFO mantığı ile çalışır.
  • İçerisinde temel bazı yapıların olması gerekmektedir.
  • node *top pointer'ı olması gerekir
  • bu top sürekli güncellenir kim gelirse o top pointerına eşitlenir.
  • static ve dynamic olanları vardır. staticler fixed size, dynamicler grow in operation

Operations

  • push()
  • pop()
  • isFull()
  • isEmpty()
    void push(int data)
    {
        if (isEmpty())
        {
            top = new node(data, nullptr);
        }
        else
        {
            top = new node(data, top);
        }
    };

Stackler için örnek bir soru postfix ler olabilir.

Queue

  • Stack benzeri bir mantık ancak FIFO yapısını kullanıyor.
  • Yazıcılardaki mantık akılda kalıcı olabilir
|-----||-----||-----||-----||-----||-----|
|Front||     ||     ||     ||     ||Rear |
|-----||-----||-----||-----||-----||-----|

Operations

  • Enqueue()
  • Dequeue()
  • isEmpty()
  • isFull()
  • clear

Static Queue

Enqueue(3);
Front & Rear
|-----||-----||-----||-----||-----||-----|
|  3  ||     ||     ||     ||     ||     |
|-----||-----||-----||-----||-----||-----|

Enqueue(5);
Front    Rear
|-----||-----||-----||-----||-----||-----|
|  3  ||  5  ||     ||     ||     ||     |
|-----||-----||-----||-----||-----||-----|

Enqueue(8);
Front           Rear
|-----||-----||-----||-----||-----||-----|
|  3  ||  5  ||  8  ||     ||     ||     |
|-----||-----||-----||-----||-----||-----|

Dynamic Queue

Enqueue(3);
|-----||-----||-----||-----|
|Front||     ||     ||Rear | ---> nullptr
|-----||-----||-----||-----|

Implementation

  • Queue yapımı için stack kullanabiliriz
class Queue
{
private:
    Stack content;
public:
    Queue(){};
    void dequeue()
    {
        Stack buffer;
        while (!content.isEmpty())
        {
            int q = content.pop();
            buffer.push(q);
        }
        buffer.pop();
        content = buffer;
    }
    void enqueue(int data)
    {
        content.push(data);
    }
    bool isEmpty()
    {
        return content.isEmpty();
    };
};

Binary Trees

    A
   / \
  B   C
 / \
D   E
   / \
  F   G
  • Her bir node iki tane pointer'ı vardır.
  • left, right diye iki tane pointerı vardır.
  • örnek bir tree node'u
struct node{
    int val;
    node* left = nullptr;
    node* right = nullptr;
}

- bir node'un altındaki devamına subtree denir

Implementation

inserting - burada recursive kullanmak daha rahat oluyor.

bool addHelper(node *&curr, int data)
{
    if (curr == nullptr)
    {
        node *newNode = new node(data);
        curr = newNode;
        return true;
    }
    else if (curr->val < data)
    {
        addHelper(curr->right, data);
    }
    else if (curr->val > data)
    {
        addHelper(curr->left, data);
    }
    else
    {
        return false;
    }
}

Traversing Trees - Inorder - Preorder - Postorder

  • Inorder
    A
   / \
  B   C
 / \
D   E
   / \
  F   G

Output: D B F E G A C
if (nodePtr)
{
    displayInOrder(nodePtr->left);
    cout << nodePtr->value << endl;
    displayInOrder(nodePtr->right);
}
  • Pre-order
    A
   / \
  B   C
 / \
D   E
   / \
  F   G

Output: A B D E F G C
if (nodePtr)
{
    cout << nodePtr->value << endl;
    displayPreOrder(nodePtr->left);     
    displayPreOrder(nodePtr->right);
}
  • Post-order
    A
   / \
  B   C
 / \
D   E
   / \
  F   G

Output: D F G E B C A
if (nodePtr)
{
    displayPostOrder(nodePtr->left);        
    displayPostOrder(nodePtr->right);
    cout << nodePtr->value << endl;
}

Useful Recursions

int noNodesHelper(node* _node){
    if(_node == nullptr){
        return 0;
    }
    else{
        return noNodesHelper(_node->left) + noNodesHelper(_node->right) + 1;
    }
}

Binary tree'ler hakkında daha detaylı sorular ve bilgiler için buradan faydalınabilir. http://cslibrary.stanford.edu/110/BinaryTrees.html

Classlar

  • Constructor
  • Destructor
  • Move Constructor
  • Copy Constructor
  • Operator overloading

Copy Constructor'ler ne zaman çağrılıyor

  • A a(b) => a'nın içine b kopyalanıyor
  • Try catch de throw yapılırken object gönderiliyorsa copy constructor çağrılır
  • A a() = b; => bunu overload ederek değiştirebiliriz
  • Eğer referans verilmeden bir fonksiyona atılırsa da kopya oluşur.

Constructor, cpy constructor ve destructor'lar tanımlanmazsa otomatik olarak compiler tarafından oluşturulur. Copy constructorlar otomatik oluşursa shallow copy oluşur.

Class oluştururken initialization list kullanılabilir. Initialization list kullanmanın avantajları object oluşmadan önce bunları set edebilmesidir. Örneğin bir const değeri bu şekilde set edebiliriz.

Point::Point() : x(0), y(0) 
{  
}

copy constructor

node(const node& cpy){

}

Operator Overloading

Return_Type  classname::operator Operator_Symbol (parameters)

// Ornekler
const myclass & myclass ::operator = (const myclass & rhs)

Bazı Önemli Overloading'ler

ostream &operator<<(ostream &os, const Name &names)
{
    os << names.name << " " << names.surname;
    return os;
}
ClockTime operator+ (const ClockTime & lhs, const ClockTime & rhs)
    ClockTime result(lhs);  //uses the default (compiler generated) copy constructor
    result += rhs;      //uses the previously defined operator+=
    return result;
}

this içinde bulunan objenin adresini döndürür. Friend Functios - Bir objenin non-public değerlerine erişmek için tanımlarız. - Fonksiyon veya class'ı friend olarak tanımlamak mümkündür.

Iterators

Bulunması gereken önemli alt parçalar. - Inıt() - HasMore() - Next() - Current()

IteratorW(const LinkedList& list ) : ll(list), current(nullptr){};
void Init(){
    // Inıt kısmında artık . ile çağırıyoruz çünkü bu bir referans
    current = ll.head;
};
bool HasMore() const{
    return (current != nullptr);
};
void Next(){
    current = current->next;
};
// Eğer değer değiştirme istersek referans olarak vermeliyiz
int & Current() const{
    return current->value;
};

Inheritance

  • Vtable virtual fonksiyonların tutulduğu bir tablodur. Bu tablo her bir derived edilen class'a konulur. Bu bir pointerdır. Örnek:
  • Constructor ve destructorlerde virtual olarak tanımlanması gerekir
class A{
    virtual int k;
}
class B : public A{
    virtual int k;
}

cout <<  sizeof(B);
#include<iostream>
using namespace std;

class Base
{
public:
    void foo()  { cout << "Base::foo() called"; }
};

class Derived: public Base
{
public:
    void foo() {  cout << "Derived::foo() called"; }
};

int main()
{
    Derived d;
    Base* w;
    w = &d;
    d.foo(); // Derived::foo() called
    w->foo(); // Base::foo() called
    return 0;
}

Move Semantics

  • R-value
  • L-value

Burada sürekli kopyalamayı enegellemek için kullanıyoruz. İki kere kopyalamak yerine bunu taşıyoruz.

int &rx = 12; // Bunu yapamıyoruz
const int &rx = 12 // Bu mümkün ancak const oluyor
int &&rx = 12; // Bu da mümkün ve rx değiştirebiliyoruz
int &&rx = foo();

Classlarda kullanılmasında move constructor kullanıyoruz.

class Array{
    Array(Array&& src); // Move consturctor 
    Array& operator=(const Array& src);
    Array& operator=(Array&& src);
}

void Array::operator=(Array&& src){
    swap(this->mem, src.mem);
    swap(this->sz, src.size)
}

std::swap

Smart Pointers

  • Kendisinin scopu'undan ayrılınca silinebilen pointerlardır.

Keywords

  • Unique_ptr => kopyalanamaz, otomatik olarak delete çağırır
  • Shared_ptr => kopyalanabilir,
  • Weak_ptr => sadece objeye erişir, deallocate yapamaz

-> * normal pointerlarda olduğu gibi kullanılabilir.

Implemantations

unique_ptr<int> ptr = make_unique<int>();

shared_ptr<int> ptr_1 = make_shared<int>(15);
shared_ptr<int> ptr_2 ;
ptr_2 = ptr_1; // Artık ikisininde adresi aynı

Shared Pointer Reference Counter

  • Shared counterlar içerisinde bir referans counter tutar. Burada eğer 0 olursa obje silinir.
  • Son kopya ölmeden obje ölmez.

Some Functions - use_count() ===> smrt_pointer.use_count() => kaç tane olduğu yazıyor. - swap() ===> swap(ptr_1,ptr_2); => iki pointerın değerlerini değiştirir.

Inheritance

Inheritance elimizdeki bir classdan yararlanarak başka classlar üretmektir.

class Ders{
    protected:
        int value;
    public:
        Ders(){};
        ~Ders(){};
        string name;
        virtual void ask() = 0; // Pure virtual function
};

class Matematik : public Ders{
    public: 
        Matematik(){};
        void ask(){
            cout << "Matematik sorusu" << endl;
        }
        int getValue(){
            return value;
        }
};
  • İlk başta base class oluşturulur ondan sonra derived class oluşturulur.
  • Silinirken de tam ters sıra ile oluşur. Stack'de oldukları için
  • base class'daki bir metodun üzerine yazmak için virtual function olarak yaparız.
  • bunu derived class'larda tanımlama zorunluluğu yoktur.
  • ancak pure virtual function olursa tanımlama zorunluluğu vardır.
  • multiple inheritance yapmak da mümkün
class Fizik: public Ders, public Bilim 
{
    //...
}

Polymorphsim

  • Polymorphism'i derived classları base class altında toplamak için kullanmaktır.
  • örneğin elimde bir çok ders var ve bunların hepsi Ders class'ından derive edilmiş
  • polymorphism yapabilmek için pointerlar veya referans ile yapmak gerekiyor
Ders* kk;
Matematik * ss;
kk = ss;
  • virtual function'lar vtable'da tutulur vtable boyutu 8 byte'dır
  • virtual fonksiyonlar destructor olarak olabilir, ancak constructor olamaz.

Exception Handling

  • örnek sorular
  • https://www.geeksforgeeks.org/c-plus-plus-gq/exception-handling-gq/

    eğer throw'un içi boş verilirse bir önceki throw'da ne atıldıysa o atılır.

Bitwise İşlemleri

  • "<<" shift left
  • ">>" shift right
  • ^ Xor Bazı güzel kullanım örnekleri
  • Bit set
a |= 1 << bit;
  • Swap
a ^= b;
b ^= a;
a ^= b;
  • x2 , /2
a << 1; // x2
b >> 1;  // /2
  • Mutlak değer alma
(n ^ (n >> 31)) - (n >> 31);
  • Bir array'de ki tek tekrar eden sayıyı bulma
int k = [1,2,3,3,2];
int sayi = 0;
for(l=0; l <k.size(); k++)
    sayi ^= k[l]
  • Swap
void swap(int *x, int *y)
{
    *x = *x ^ *y;
    *y = *x ^ *y;
    *x = *x ^ *y;
}

Threads & Concurrency

Kodu compile edebilmek için -pthread ile vermek gerekiyor gcc için.

  • Bir program başladığı zaman bir process başlar
  • Virtual memory'i kullanırız.
  • Virtual addresler pointerların yerini gösteriyor bunlarda fiziksel memory'deki yerlerini işaret ediyor.
  • Virtual memoru (İşletim Sistemleri dersinde öğretiliyor)

Thread nedir? Bilgisayarda çalışan bir process dir. - is a path of execution - her process en az bir threadi vardır. buna da main thread denir

  • Multithreadingin amacı concurrency elde etmektir.
  • Parallelism için fiziksel proccess unitler lazım.
  • Multithrad de buna gerek yoktur.
  • Tek bir core varsa concurrency elde etmeye çalışırız.
  • birden çok core varsa parallelism elde ederiz.

Kısa süre aralıklarla threadler işlemci tarafından çalıştırılır. Aslında sadece tek bir core var.

  • main threadden child threadler oluşturabilirsin.

Do we need parallelism for concurrency? - eski zamanlarda ghz leri yüksek bilgisayarlar varmış tek core işlemciler var. ancak bunların kullanımı sıkıntılı - günümüzde multicore ancak ghz ler daha düşük

c++ multithread - c++ 11'e kadar standart bir thread yoktu. - pthread ile standart bir hale geldi - std::thread ile - main fonksiyonu main threadi temsil eder

#include <iostream>
#include <thread>
using namespace std;

void hello() {
  cout << "Hello thread\n";
}

int main() {
  thread aThread(&hello); // non blocking element programı bloklamıyor hemen aşağıya iniyor
  aThread.join(); // blocking element main thread bu kodun bitmesini gerekiyor ve aşağıya inmiyor
  cout << "ye main\n";
  return 0; 
}

Threadlerde ana iki işlem vardır bunlar join ve detatch dir join => program thread'in bitmesini bekliyor diğer threadler çalışıyor arkada join ettikten sonra kendisini destruct edebiliyor

detach => artık joinable olmuyor işlemi bitiyor main thread için aThrad.joinable() diye kullanabiliyoruz.

kodu join etmeden kullanırsak hata alırız.

    chrono::seconds dura(2);
    this_thread::sleep_for(dura); // Thread uyuyor

detach nedir?

detach join edilemez hale getiriyor

başka özellikler

get_id ==> thread'lerin unique id'leri var. id geri döner sleep_until ==> thread'i uyutmak için kullanırız. sleep_for ==> n uyutmak yield => reschedule yapmaya yarıyor

Threadleri beraber nasıl çalıştıracağız

struct Counter {
    int value;
    Counter : value(0){}

    void increment(){
        ++value;
    }
}

Bunun sonucunun ne çıkacağını bilemeyiz 1 veya 2 çıkabilir. Atomik bir işlem değil. Senron edebilmek için bazı data strutcurları kullanabilir veya atomik hale getirebiliriz. Multithread uygulamaları düzenlemeye scheduling denir. Eğer senkronize işlemlerini doğru yapılmazsa deadlock oluşabilir. kodları sync edebilmek için std::atomic keyword'unü kullanabiliriz. ! counter örneği düşünürsek referans olarak vermemiz gerekiyor bunun için ref(counter) diyererek referanslayabiliriz.

atomic<int> value;

Sync Sıkıntıları (Producer - Consumer Problemi)

tek bir producer ve consumer olursa herhangi bir sıkıntı yok ancak birden çok olursa sıkıntı oluyor örnek * Thread 1: data üretip queue koy * Thread 2: queue kontrol et eğer varsa datayı sil * Thread 3: queue kontrol et eğer varsa datayı sil buradaki sıkıntı ortak queue kullanıyor. eğer tek bir data varsa aynı anda ikisinin queue empty olmadığını görür ikisi de dequeue etmeye çalışırsa programda probelem oluşur.

Mutex (Mutual Exclusion)

  • lock veya unlock olabilir
  • binary counter lock ypatığımız zamaan arttırıyor, unlock yaptığımız zaman azaltıyor
mutex mut;

void increment(){
    mut.lock();
    increment ++;
    mut.unlock();
}
  • atomic mutexlerden kat ve kat daha hızlıdır.

Kodun içerisinde exception varsa ne zaman lock veya unlock olduğunu bilemiyoruz.

lock_guard<std::mutex> l(mut) kullanarak güvenli bir şekilde lock ve unlock yapabiliriz

mutex'i lock ettikten sonra tekrar lock edemeyiz. unlock etmek gerekiyor. mutex aynı anda lock edilebilir bu da deadlock oluşturabiliyoru. bunu engellemek için recursive mutex kullanırız.

struct Complex {
recursive_mutex mutex;
double i;

Complex() : i(1) {}

void mul(double x){
    lock_guard<std::recursive_mutex> lock(mutex);
    i *= x;
}
void div(double x){
    lock_guard<std::recursive_mutex> lock(mutex);
    i /= x;
}
void both(double x, double y){
    lock_guard<std::recursive_mutex> lock(mutex);
    mul(x);
    div(y);
}
};

mutex'i belirli bir süre kilitlemek içi timex_mutex kullanabiliriz. veya recursive_timed_mutex de kullanabiliriz.

producer consumer kodlarında ortak beklemek için while kullanabiliriz.

std::lock sayesinde aynı anda birden çok mutex'i aynı anda lock edebiliriz. multiple mutex varsa çok önemli. içeri sıralaması önemlidir.

promise & future

Threadler arasında iletişim kurabilmek mümkündür. Bunu da future kullanarak yapabiliriz. shared state future::get kullanarak yapabiliriz. Promise future objesinden geliyor. bir örnek

void foo(promise<string> & prms) {
  string str = "Hello from the thread";
  prms.set_value(str);
}

int main() {
  promise<string> prms;
  future<string> ftr = prms.get_future();
  thread thr(&foo, ref(prms));
  cout << ftr.get() << endl; 
  thr.join();
  return 1;
}

burada join olmadan önce bile set_value olmadan bile ftr.get yazdıramıyor. blocking element görevini görüyor.

prms.set_exception(current_exception()); // => diyerek exception handling kullanabiliriz. 

async

async ile bu işlemler çok daha rahat oluyor.

string foo() {
  string str = "Hello from the thread";
  return str;
}

int main() {
  auto ftr = async(&foo); // async future object döndürüyor
  cout << "Hello from the main" << endl;
  auto str = ftr.get();
  cout << str << endl;
  return 1;
}

dining philosopher problem


This was the end of the blog post. You can reach me via email umusasadik at gmail com