1. 程式人生 > >【C++標準庫】並發

【C++標準庫】並發

不可 include efault eve .get exc library fun join()

高級接口async()和future

/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
* by Nicolai M. Josuttis, Addison-Wesley, 2012
*
* (C) Copyright Nicolai M. Josuttis 2012.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/ #include <future> #include <thread> #include <chrono> #include <random> #include <iostream> #include <exception> using namespace std; int doSomething(char c) { // random-number generator (use c as seed to get different sequences) std::default_random_engine
dre(c); std::uniform_int_distribution
<int> id(10, 1000); // loop to print character after a random period of time for (int i = 0; i<10; ++i) { this_thread::sleep_for(chrono::milliseconds(id(dre))); cout.put(c).flush(); } return c; } int func1() { return
doSomething(.); } int func2() { return doSomething(+); } int main() { std::cout << "starting func1() in background" << " and func2() in foreground:" << std::endl; // start func1() asynchronously (now or later or never): std::future<int> result1(std::async(func1)); int result2 = func2(); // call func2() synchronously (here and now) // print result (wait for func1() to finish and add its result to result2 int result = result1.get() + result2; std::cout << "\nresult of func1()+func2(): " << result << std::endl; }

技術分享圖片

class std::future提供了“處理並發運算之未來結果”的能力,但是get()只能調用一次,第二次調用get()會導致不可預期的行為。然而有時候,多次處理並發結果是合理的,特別是當多個線程都想處理這個結果時。基於這個目的,C++標準庫提供了class std::shared_future,可以多次調用get(),得到相同的結果,或導致拋出一個異常。

技術分享圖片
/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
* by Nicolai M. Josuttis, Addison-Wesley, 2012
*
* (C) Copyright Nicolai M. Josuttis 2012.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <future>
#include <thread>
#include <iostream>
#include <exception>
#include <stdexcept>
using namespace std;

int queryNumber()
{
    // read number
    cout << "read number: ";
    int num;
    cin >> num;

    // throw exception if none
    if (!cin) {
        throw runtime_error("no number read");
    }

    return num;
}

void doSomething(char c, shared_future<int> f)
{
    try 
    {
        // wait for number of characters to print
        int num = f.get();  // get result of queryNumber()

        for (int i = 0; i<num; ++i) 
        {
            this_thread::sleep_for(chrono::milliseconds(100));
            cout.put(c).flush();
        }
    }
    catch (const exception& e)
    {
        cerr << "EXCEPTION in thread " << this_thread::get_id()
            << ": " << e.what() << endl;
    }
}

int main()
{
    try 
    {
        // start one thread to query a number
        shared_future<int> f = async(queryNumber);

        // start three threads each processing this number in a loop
        auto f1 = async(launch::async, doSomething, ., f);
        auto f2 = async(launch::async, doSomething, +, f);
        auto f3 = async(launch::async, doSomething, *, f);

        // wait for all loops to be finished
        f1.get();
        f2.get();
        f3.get();
    }
    catch (const exception& e) 
    {
        cout << "\nEXCEPTION: " << e.what() << endl;
    }
    cout << "\ndone" << endl;
}
View Code

低層接口:Thread和Promise

/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
* by Nicolai M. Josuttis, Addison-Wesley, 2012
*
* (C) Copyright Nicolai M. Josuttis 2012.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <thread>
#include <chrono>
#include <random>
#include <iostream>
#include <exception>
using namespace std;

void doSomething(int num, char c)
{
    try 
    {
        // random-number generator (use c as seed to get different sequences)
        default_random_engine dre(42 * c);
        uniform_int_distribution<int> id(10, 1000);
        for (int i = 0; i<num; ++i) 
        {
            this_thread::sleep_for(chrono::milliseconds(id(dre)));
            cout.put(c).flush();
            //...
        }
    }
    // make sure no exception leaves the thread and terminates the program
    catch (const exception& e) {
        cerr << "THREAD-EXCEPTION (thread "
            << this_thread::get_id() << "): " << e.what() << endl;
    }
    catch (...) {
        cerr << "THREAD-EXCEPTION (thread "
            << this_thread::get_id() << ")" << endl;
    }
}

int main()
{
    try 
    {
        thread t1(doSomething, 5, .);  // print five dots in separate thread
        cout << "- started fg thread " << t1.get_id() << endl;

        // print other characters in other background threads
        for (int i = 0; i<5; ++i) {
            thread t(doSomething, 10, a + i); // print 10 chars in separate thread
            cout << "- detach started bg thread " << t.get_id() << endl;
            t.detach();  // detach thread into the background
        }

        cin.get();  // wait for any input (return)

        cout << "- join fg thread " << t1.get_id() << endl;
        t1.join();  // wait for t1 to finish
    }
    catch (const exception& e) {
        cerr << "EXCEPTION: " << e.what() << endl;
    }
}

技術分享圖片

/* The following code example is taken from the book
* "The C++ Standard Library - A Tutorial and Reference, 2nd Edition"
* by Nicolai M. Josuttis, Addison-Wesley, 2012
*
* (C) Copyright Nicolai M. Josuttis 2012.
* Permission to copy, use, modify, sell and distribute this software
* is granted provided this copyright notice appears in all copies.
* This software is provided "as is" without express or implied
* warranty, and with no claim as to its suitability for any purpose.
*/
#include <thread>
#include <future>
#include <iostream>
#include <string>
#include <exception>
#include <stdexcept>
#include <functional>
#include <utility>

void doSomething(std::promise<std::string>& p)
{
    try {
        // read character and throw exception if ‘x‘
        std::cout << "read char (‘x‘ for exception): ";
        char c = std::cin.get();
        if (c == x) {
            throw std::runtime_error(std::string("char ") + c + " read");
        }
        //...
        std::string s = std::string("char ") + c + " processed";
        p.set_value_at_thread_exit(std::move(s));    // store result
    }
    catch (...) {
        p.set_exception_at_thread_exit(std::current_exception());  // store exception
    }
}

int main()
{
    try 
    {
        // create a promise to store the outcome
        std::promise<std::string> p;
        // create a future to process the outcome
        std::future<std::string> f(p.get_future());
        // start a thread using the promise to store the outcome
        std::thread t(doSomething, std::ref(p));
        t.detach();
        //...

        // process the outcome
        std::cout << "result: " << f.get() << std::endl;
    }
    catch (const std::exception& e) 
    {
        std::cerr << "EXCEPTION: " << e.what() << std::endl;
    }
    catch (...) 
    {
        std::cerr << "EXCEPTION " << std::endl;
    }
}

【C++標準庫】並發