• 【C++标准库】并发


    高级接口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 << "
    result 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 << "
    EXCEPTION: " << e.what() << endl;
        }
        cout << "
    done" << 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;
        }
    }
  • 相关阅读:
    PRML 读书记录
    What’s the difference between Taxonomies and Ontologies? Ask Dr. Search
    C#中IP地址转换为数值的方法
    [转]读《简约至上》有感 及我的支语片言
    读《一名毕业生的程序员之路》有感
    [转载]温故知新 javascript 正则表达式
    [转]jQuery 1.9 移除了 $.browser 的替代方法
    QQ网盘首页,这样也能上线!做产品的人是白痴啊!
    [转]P3P解决cookie存取的跨域问题
    【转】跨浏览器“复制到粘贴板”JavaScript代码
  • 原文地址:https://www.cnblogs.com/larry-xia/p/9519949.html
Copyright © 2020-2023  润新知