---------------
void print_id(thread& t)
{
    if (t.get_id()==id{})
        cout << "t nie da si czy\n";
    else
        cout << "id t to " << t.get_id() << '\n';
}
---------------
void f0();    // brak argumentw
void f1(int); // jeden argument typu int

thread t1 {f0};
thread t2 {f0,1};                  // bd: za duo argumentw
thread t3 {f1};                    // bd: za mao argumentw
thread t4 {f1,1};
thread t5 {f1,1,2};                // bd: za duo argumentw
thread t3 {f1,"Jestem guptasem"}; // bd: niepoprawny typ argumentu
---------------
template<typename T>
class Sync_queue<T> { // kolejka udostpniajca operacje put() i get() wolne od wycigw do danych (42.3.4)
    //...
};

struct Consumer {
    Sync_queue<Message>& head;
    Consumer(Sync_queue<Message>& q) :head(q) {}
    void operator()(); // pobiera operacje z pocztku
};

struct Producer {
    Sync_queue<Message>& tail;
    Consumer(Sync_queue<Message>& q) :tail(q) {}
    void operator()(); // wstawia wiadomoci na kocu
};

Sync_queue<Message> mq;
Consumer c {mq}; // tworzy zadania i "wie je razem"
Producer p {mq};

thread pro {p};  // w kocu uruchamia wtki
thread con {c};
//...
---------------
void my_task(vector<double>& arg);

void test(vector<double>& v)
{
    thread my_thread1 {my_task,v};           // ups: przekazanie kopii v
    thread my_thread2 {my_task,ref(v)};      // OK: przekazanie v przez referencj
    thread my_thread3 {[&v]{ my_task(v); }}; // OK: uniknicie problemu ref()
    //...
}
---------------
vector<thread> worker(1000); // 1000 domylnych wtkw

for (int i=0; i!=worker.size(); ++i) {
    //... oblicza argument dla worker[i] oraz tworzy wtek roboczy tmp...
    worker[i] = move(tmp);
}
---------------
void heartbeat()
{
    while(true) {
        output(steady_clock::now());
        this_thread::sleep_for(second{1}); // 42.2.6
    }
}

void run()
{
    thread t {heartbeat};
}   // zamknicie programu, bo heartbeat() nadal dziaa po zakoczeniu zakresu t
---------------
void tick(int n)
{
    for (int i=0; i!=n; ++i) {
        this_thread::sleep_for(second{1}); // 42.2.6
        output("yje!");
    }
}

int main()
{
    thread timer {tick,10};
    timer.join();
}
---------------
void run(int i, int n) // ostrzeenie: kod bardzo niskiej jakoci
{
    thread t1 {f};
    thread t2;
    vector<Foo> v;
    //...
    if (i<n) {
        thread t3 {g};
        //...
        t2 = move(t3);  // przenosi t3 do zewntrznego zakresu
    }
    v[i] = Foo{}; // moe zgosi wyjtek
    //...
    t1.join();
    t2.join();
}
---------------
struct guarded_thread : thread {
    using thread::thread; // 20.3.5.1
    ~guarded_thread() { if (joinable()) join(); }
};
---------------
void run2(int i, int n) // proste uycie stranika
{
    guarded_thread t1 {f};
    guarded_thread t2;
    vector<Foo> v;
    //...
    if (i<n) {
        thread t3 {g};
        //...
        t2 = move(t3);  // przenosi t3 do zewntrznego zakresu
    }
    v[i] = Foo{}; // moe zgosi wyjtek
    //...
}
---------------
void run2()
{
    thread t {heartbeat};
    t.detach(); // niech wtek heartbeat dziaa niezalenie
}
---------------
vector<thread> my_threads;  // przechowuje odpite wtki

void run()
{
    thread t {heartbeat};
    my_threads.push_back(move(t));
    //...
    my_threads.emplace_back(tick,1000);
}

void monitor()
{
    for (thread& t : my_threads)
        cout << "wtek " << t.get_id() << '\n';
}
---------------
void home() // nie rb tego
{
    int var;
    thread disaster{[&]{ this_thread::sleep_for(second{7.3});++var; }}
    disaster.detach();
}










---------------
void helper(thread& t)
{
    thread::id me {this_thread::get_id()};
    //...
    if (t.get_id()!=me) t.join();
    //...
}
---------------
template<typename K, typename V>
class Map {
public:
    Map();
    //...
    static void set_default(const K&,V&); // ustawia warto domyln dla wszystkich
                                          // sownikw typu Map<K,V>
private:
    static pair<const K,V> default_value;
};
---------------
// gdzie w wtku 1:
    Map<string,int>::set_default("Heraclides",1);
// gdzie w wtku 2:
    Map<string,int>::set_default("Zeno",1);
---------------
template<typename K, typename V>
class Map {
    //...
private:
    static thread_local pair<const K,V> default_value;
};
---------------
mutex cout_mutex; // reprezentuje prawo do uywania cout

template<typename Arg1, typename Arg2, typename Arg3>
void write(Arg1 a1, Arg2 a2 = {}, Arg3 a3 = {})
{
    thread::id name = this_thread::get_id();
    cout_mutex.lock();
    cout << "Z wtku " << name << " : " << a1 << a2 << a3;
    cout_mutex.unlock();
}
---------------
mutex cout_mutex; // inicjacja do stanu "nie posiadany przez aden wtek"
void hello()
{
    cout_mutex.lock();
    cout << "Wiatj, ";
    cout_mutex.unlock();
}

void world()
{
    cout_mutex.lock();
    cout << "wiecie!";
    cout_mutex.unlock();
}

int main()
{
    thread t1 {hello};
    thread t2 {world};

    t1.join();
    t2.join();
}
---------------
Witaj, wiecie!
---------------
wiecie!Witaj,
---------------
extern mutex wqm;
extern list<Work> wq;

void composer()
{
    list<Work> requests;

    while (true) {
        for (int i=0; i!=10; ++i) {
            Work w;
            //... tworzy danie pracy...
            requests.push_back(w);
        }
        if (wqm.try_lock()) {
            wq.splice(requests); // wstawia dania do listy (31.4.2)
            wqm.unlock();
        }
    }
}
---------------
template<typename Arg, typename... Args>
void write(Arg a, Args tail...)
{
    cout_mutex.lock();
    cout << a;
    write(tail...);
    cout_mutex.unlock();
}
---------------
recursive_mutex cout_mutex; // zmiana na recursive_mutex, aby unikn zakleszczenia

template<typename Arg, typename... Args>
void write(Arg a, Args tail...)
{
    cout_mutex.lock();
    cout << a;
    write(tail...);
    cout_mutex.unlock();
}
---------------
mutex mtx;
try{
    mtx.lock();
    mtx.lock(); // druga prba zablokowania
}
catch (system_error& e) {
    mtx.unlock();
    cout << e.what() << '\n';
    cout << e.code() << '\n';
}
---------------
device or resource busy
generic: 16
---------------
extern timed_mutex imtx;
extern Image buf;

void next()
{
    while (true) {
        Image next_image;
        //... obliczenia...

        if (imtx.try_lock_for(milliseconds{100})) {
            buf = next_image;
            imtx.unlock();
        }
    }
}
---------------
void use(mutex& mtx, Vector<string>& vs, int i)
{
    mtx.lock();
    if (i<0) return;
    string s = vs[i];
    //...
    mtx.unlock();
}

---------------
void use(mutex& mtx, vector<string>& vs, int i)
{
    lock_guard<mutex> g {mtx};
    if (i<0) return;
    string s = vs[i];
    //...
}
---------------
void use(mutex& mtx, vector<string>& vs, int i)
{
    if (i<0) return;
    lock_guard<mutex> g {mtx};
    string s = vs[i];
    //...
}
---------------
void use(mutex& mtx, vector<string>& vs, int i)
{
    if (i<0) return;
    string s;
    {
        lock_guard<mutex> g {mtx};
        s = vs[i];
    }
    //...
}

---------------
mutex mtx;
timed_mutex mtx2;

void use()
{
    unique_lock<mutex> lck {mtx,defer_lock};  // defer_lock to obiekt typu defer_lock_t
    unique_lock<timed_mutex> lck2 {mtx2,defer_lock};

    lck.try_lock_for(milliseconds{2});  // bd: muteks nie ma skadowej try_lock_for()

    lck2.try_lock_for(milliseconds{2}); // OK
    lck2.try_lock_until(steady_clock::now()+milliseconds{2});
    //...
}
---------------
timed_mutex mtx2;

void use2()
{
    unique_lock<timed_mutex> lck2 {mtx2,milliseconds{2}};
    if (lck2.owns_lock()) {
        // zajcie powiodo si:
        //... jakie dziaania...
    }
    else {
        // czas min:
        //... jakie inne dziaania...
    }
}
---------------
mutex mtx1; // chroni jeden zasb
mutex mtx2; // chroni inny zasb

void task(mutex& m1, mutex& m2)
{
    unique_lock<mutex> lck1 {m1};
    unique_lock<mutex> lck2 {m2};
    //... uycie zasobw...
}

thread t1 {task,ref(mtx1),ref(mtx2)};
thread t2 {task,ref(mtx2),ref(mtx1)};

---------------
template <typename M1, typename... Mx>
int try_lock(M1& mtx, Mx& tail...)
{
    if (mtx.try_lock()) {
        int n = try_lock(tail...);
        if (n == -1) return -1; // wszystkie blokady zostay zajte
        mtx.unlock();           // wycofanie
        return n+1;
    }
    return 1;                   // nie udao si zaj mtx
}

template <typename M1>
int try_lock(M1& mtx)
{
    return (mtx.try_lock()) ? -1 : 0;
}
---------------
void task(mutex& m1, mutex& m2)
{
    unique_lock<mutex> lck1 {m1,defer_lock};
    unique_lock<mutex> lck2 {m2,defer_lock};
    lock(lck1,lck2);
    //... uycie zasobw...
}
---------------
class X {
public:
    X();
    //...
private:
    //...
    static once_flag static_flag;
    static Y static_data_for_class_X;
    static void init();
};

X::X()
{
    call_once(static_flag,init());
}
---------------
Color& default_color() // kod uytkownika
{
    static Color def { read_from_environment("kolor ta") };
    return def;
}
---------------
Color& default_color() // wygenerowany kod
{
    static Color def;
    static_flag __def;
    call_once(__def,read_from_environment,"kolor ta");
    return def;
}
---------------
enum class cv_status { no_timeout, timeout };
---------------
while (queue.empty()) wait(queue_lck);
---------------
void simple_timer(int delay)
{
    condition_variable timer;
    mutex mtx;                               // muteks chronicy czasomierz
    auto t0 = steady_clock::now();
    unique_lock<mutex> lck(mtx);             // zajmuje mtx
    timer.wait_for(lck,milliseconds{delay}); // zwalnia i ponownie zajmuje mtx
    auto t1 = steady_clock::now();
    cout << duration_cast<milliseconds>(t1-t0).count() << "milisekund oczekiwania\n";
} // niejawne zwolnienie mtx
---------------
template<typename T>
class Sync_queue {
public:
    void put(const T& val);
    void put(T&& val);
    void get(T& val);
private:
    mutex mtx;
    condition_variable cond;
    list<T> q;
};
---------------
template<typename T>
void Sync_queue::put(const T& val)
{
    lock_guard<mutex> lck(mtx);
    q.push_back(val);
    cond.notify_one();
}
---------------
template<typename T>
void Sync_queue::get(T& val)
{
    unique_lock<mutex> lck(mtx);
    cond.wait(lck,[this]{ return !q.empty(); });
    val=q.front();
    q.pop_front();
}
---------------
Sync_queue<Message> mq;

void producer()
{
    while (true) {
        Message m;
        //... zapenia m...
        mq.put(m);
    }
}

void consumer()
{
    while (true) {
        Message m;
        mq.get(m);
        //... uywa m...
    }
}

thread t1 {producer};
thread t2 {consumer};
---------------
void consumer()
{
    while (true) {
        Message m;
        mq.get(m,milliseconds{200});
        //... uycie m...
    }
}
---------------
template<typename T>
void Sync_queue::get(T& val, steady_clock::duration d)
{
    unique_lock<mutex> lck(mtx);
    bool not_empty = cond.wait_for(lck,d,[this]{ return !q.empty(); });
    if (not_empty) {
        val=q.front();
        q.pop_front();
    }
    else
        throw system_error{"Sync_queue: get() - upyn limit czasu"};
}
---------------
template<typename T>
void Sync_queue::put(T val, steady_clock::duration d, int n)
{
    unique_lock<mutex> lck(mtx);
    bool not_full = cond.wait_for(lck,d,[this]{ return q.size()<n; });
    if (not_full) {
        q.push_back(val);
        cond.notify_one();
    }
    else {
        cond.notify_all();
        throw system_error{"Sync_queue: put() - upyn limit czasu"};
    }
}

---------------
res = task(args);  // wykonuje zadanie przy uyciu argumentw i zwraca wynik
---------------
auto handle = async(task,args);  // wykonuje zadanie przy uyciu argumentw
//... robi co innego...
res = handle.get()               // pobiera wynik

---------------
promise<map<string,int>> pr;
map<string,int>> m;
//... napenia m milionem par <string,int>...
pr.set_value(m);
---------------
try{
    pr.set_value(f(args)); // zaoenie, e promise nazywa si pr
}
catch(...) {
    pr.set_exception(current_exception());
}
---------------
int ff(int i)
{
    if (i) return i;
    throw runtime_error("ff(0)");
}
---------------
packaged_task<int(int)> pt1 {ff}; // zapisuje ff w pt1
packaged_task<int(int)> pt2 {ff}; // zapisuje ff w pt2

pt1(1); // pt1 wywouje ff(1);
pt2(0); // pt2 wywouje ff(0);
---------------
auto v1 = pt1.get_future();
auto v2 = pt2.get_future();

try{
    cout << v1.get() << '\n'; // drukuje
    cout << v2.get() << '\n'; // zgasza wyjtek
}
catch (exception& e) {
    cout << "wyjtek: " << e.what() << '\n';
}
---------------
1
wyjtek: ff(0)
---------------
try{
    cout << ff(1) << '\n'; // drukuje
    cout << ff(0) << '\n'; // zgasza wyjtek
}
catch (exception& e) {
    cout << "wyjtek: " << e.what() << '\n';
}
---------------
using Res = /* typ wyniku dla serwera */;
using Args = /* typy argumentw dla serwera */;
using PTT = Res(Args);

Sync_queue<packaged_task<PTT>> server;

Res f(Args);                       // funkcja: robi co
struct G {
    Res operator()(Args);          // obiekt funkcyjny: robi co
    //...
};
auto h = [=](Args a) { /* robi co */}; // lambda

packaged_task<PTT> job1(f);
packaged_task<PTT> job2(G{});
packaged_task<PTT> job3(h);

auto f1 = job1.get_future();
auto f2 = job2.get_future();
auto f3 = job3.get_future();

ser ver.put(move(job1));
ser ver.put(move(job2));
ser ver.put(move(job3));

auto r1 = f1.get();
auto r2 = f2.get();
auto r3 = f3.get();
---------------
template<typename T>
vector<T> wait_for_all(vector<future<T>>& vf)
{
    vector<T> res;
    for (auto& fu : vf)
        res.push_back(fu.get());
    return res;
}
---------------
future_status s = fu.wait_for(seconds{0});
---------------
template<typename T>
int wait_for_any(vector<future<T>>& vf, steady_clock::duration d)
    // zwraca indeks gotowego obiektu future
    // jeli aden taki obiekt nie jest gotowy, czeka przez d czasu i sprawdza ponownie
{
    while(true) {
        for (int i=0; i!=vf.size(); ++i) {
            if (!vf[i].valid()) continue;
            switch (vf[i].wait_for(seconds{0})) {
            case future_status::ready:
                return i;
            case future_status::timeout:
                break;
            case future_status::deferred:
                throw runtime_error("wait_for_all(): odroczony future");
            }
        }
        this_thread::sleep_for(d);
    }
}
---------------
double square(int i) { return i*i; }

future<double> fd = async(square,2);
double d = fd.get();
---------------
double square(int i) { return i*i; }

auto fd = async(square,2);
auto d = fd.get();

---------------
double d = 4;
---------------
void user()
{
    auto handle = async([](){ return input_interaction_manager(); });
    //...
    auto input = handle.get();
    //...
}
---------------
extern vector<Record> goods; // dane do przeszukania
---------------
template<typename Pred>
Record*find_rec(vector<Record>& vr, int first, int last, Pred pr)
{
    vector<Record>::iterator p = std::find_if(vr.begin()+first,vr.begin()+last,pr);
    if (p == vr.begin()+last)
        return nullptr;  // koniec: nie znaleziono rekordu
    return &*p;          // znaleziono: zwrot wskanika do elementu
}
---------------
const int grain = 50000; // liczba rekordw do przeszukania liniowego
---------------
template<typename Pred>
Record* pfind(vector<Record>& vr, Pred pr)
{
    assert(vr.size()%grain==0);

    vector<future<Record*>> res;

    for (int i = 0; i!=vr.size(); i+=grain)
        res.push_back(async(find_rec<Pred>,ref(vr),i,i+grain,pr));

    for (int i = 0; i!=res.size(); ++i) // szuka wyniku w obiektach future
        if (auto p = res[i].get())      // czy zadanie znalazo element?
            return p;

    return nullptr;                     // nic nie znaleziono
}
---------------
void find_cheap_red()
{
    assert(goods.size()%grain==0);

    Record* p = pfind(goods,
                     [](Record& r) { return r.price<200 && r.color==Color::red; });
    cout << "record "<< *p << '\n';
}
---------------
template<typename Pred>
Record* pfind_any(vector<Record>& vr, Pred pr)
{
    vector<future<Record*>> res;

    for (int i = 0; i!=vr.size(); i+=grain)
        res.push_back(async(find_rec<Pred>,ref(vr),i,i+grain,pr));

    for (int count = res.size(); count; --count) {
        int i = wait_for_any(res,microseconds{10});  // znajduje ukoczone zadanie
        if (auto p = res[i].get())                   // czy zadanie co znalazo?
            return p;
    }

    return nullptr;                                  // nic nie znaleziono
}
---------------
template<typename Pred>
vector<Record*> find_all_rec(vector<Record>& vr, int first, int last, Pred pr)
{
    vector<Record*> res;
    for (int i=first; i!=last; ++i)
        if (pr(vr[i]))
            res.push_back(&vr[i]);
    return res;
}
---------------
template<typename Pred>
vector<Record*> pfind_all(vector<Record>& vr, Pred pr)
{
    vector<future<vector<Record*>>> res;

    for (int i = 0; i!=vr.size(); i+=grain)
        res.push_back(async(find_all_rec<Pred>,ref(vr),i,i+grain,pr));

    vector<vector<Record*>> r2 = wait_for_all(res);

    vector<Record*>r;
    for (auto& x : r2) // poczenie wynikw
        for (auto p : x)
            r.push_back(p);
    return r;
}
---------------
void find_all_cheap_red()
{
    asser t(goods.size()%grain==0);

    auto vp = pfind_all(goods,
         [](Record& r) { return r.price<200 && r.color==Color::red; });
    for (auto p : vp)
        cout << "record "<< *p << '\n';
}
---------------
void just_find_cheap_red()
{
    auto p = find_if(goods.begin(),goods.end(),
         [](Record& r) { return r.price<200 && r.color==Color::red; });
    if (p!=goods.end())
        cout << "record "<< *p << '\n';
    else
        cout << "nie znaleziono\n";
}

void just_find_all_cheap_red()
{
    auto vp = find_all_rec(goods,0,goods.size(),
         [](Record& r) { return r.price<200 && r.color==Color::red; });
    for (auto p : vp)
        cout << "record "<< *p << '\n';
}