Concurrency 2, thread and promise - C++11, 9 of n

1) Low level interfaces:
  • std::thread<>, can be treated as a counterpart of std::async<>(launch::async, ...)
  • std::promise<>, can be treated as a counterpart of std::future<>, it enables you to provide the data (by using one of its set_...() functions) and All member functions that set the value or exception are thread safe

Example:
#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 exceptiopn 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(std::move(s)); // store result
    }
    catch (...) {
        p.set_exception(std::current_exception()); // store exception
    }
}
int main()
{
    try {
        // start thread using a promise to store the outcome
        std::promise<std::string> p;
        std::thread t(doSomething,std::ref(p));
        t.detach();
        ...
        // create a future to process the outcome
        std::future<std::string> f(p.get_future());
       // 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;
    }
}
What happened to p.set_value() or p.set_exception() ?
This makes the promise<> object ready
How to get the result from the promise<> object
We need a corresponding future<> object sharing the same shared state of promise<> to retrieve the result. f.get() may block until promise<> object gets ready.
What if we need wait until the thread ends and then gets the result from promise<> object ?
When promise<> object gets ready, it doesn't mean that the thread really ends.  To ensure the cleanup of thread local objects and other stuff before the result gets processed, we need call set_value_at_thread_exit() or set_exception_at_thread_exit() instead.

2) Gotchas:

  • Note: thread<>::join(), thread<>::detach() should be called before the lifetime of a thread object ends or a new thread gets move assigned. Otherwise, the program aborts with std::terminate().
  • thread<>::get_id() returns std::thread::id() which means 'no thread' if the thread is detached. It is joinable, a unique thread id will be returned.
  • Pay special attention to detached thread (Don't use detached thread whenever possible):
    1. Detached threads should prefer to access local copies only.
    2. If a detached thread uses a global or static object, you should do one of the following:
      • Ensure that these global/static objects are not destroyed before all detached threads accessing them are finished (or finished accessing them). One approach to ensure this is to use condition variables, which the detached threads use to signal that they have finished. Before leaving main() or calling exit(), you’d have to set these condition variables then to signal that a destruction is possible. Ideally, you should use notify_all_at_thread_exit() to set the condition variable to ensure that all thread local variables are destructed
      • End the program by calling quick_exit(), which was introduced exactly for this reason to end a program without calling the destructors for global and static objects

3) packaged_task<>
It gives the ability of processing the outcome of a background task that you don’t necessarily start immediately.
double compute (int x, int y);
...
std::packaged_task<double(int,int)> task(compute); // create a task
std::future<double> f = task.get_future(); // get its future
...
task(7,5); // start the task (typically but not necessary in a separate thread)
...
double res = f.get(); // wait for its end and process result/exception

4) this_thread namespace

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值