The C + + standard library uses the expectation (future) to support the wait for one-time events. The thread that waits for a one-time event can get an expectation representing the event. This thread can periodically query this expectation for every interval of events. In addition, the thread can continue to do other processing until it waits for the one-time event to be suspended. You can also pass data through expectations.
The C + + standard library provides two expectations of unique future (std::future<>) and Shared Futures (std::shared_future<>), both declared in <future> The library header file. An Std::future instance can only be associated to an event. Multiple std::shared_future can be associated to the same event. When a shared expectation is associated with an event to occur, all expected instances will be woken at the same time to access the event. Because you expect to be able to correlate data, you expect to be a template class that uses std::future<void> and std::shared_future<void> when no data is associated with expectations. Although it is expected to be used for inter-thread communication, but the expected object does not support synchronous access, we need mechanisms such as mutexes to protect access to them by different threads.
Let's say we have a computation operation that takes a long time, and we're going to use its calculations, and we can do some other things before we need the results. We can start a new thread to do the calculation. Std:;thread does not have a direct mechanism to meet our needs. This function can be achieved using the Std::async function template.
Std::async can start an asynchronous thread, and we don't have to start waiting for the asynchronous thread to finish as soon as we use thread, and Std::async will return a desired object that will eventually be used to store the return result of the asynchronous thread. When we need this result, calling wait on the expected object will block the thread until it is expected to be ready. Examples are as follows:
#include <future> #include <iostream>int find_the_answer_to_ltuae () { return 42;} void Do_other_stuff () {}int main () { std::future<int> the_answer=std::async (find_the_answer_to_ltuae); Do_other_stuff (); std::cout<< "The answer is" <<the_answer.get () <<std::endl;
Std::async allows us to pass extra arguments to the function. If the first argument is a member function pointer, the second parameter is the pointer to the object that corresponds to the member function, and the other parameter is the argument passed to the member function. Otherwise, the second and subsequent arguments are the arguments passed to the function or callable object that is the first parameter.
#include <string> #include <future>struct x{ void foo (int,std::string const&); std::string Bar (std::string const&); X x;//call X->foo ("Hello"), Auto F1=std::async (&x::foo,&x,42, "Hello");//Call Tmpx.bar ("Goodbye"); TMPX is the copy of X Auto F2=std::async (&x::bar,x, "goodbye"); struct y{ double operator () (double);}; Y y;//calls Tmpy (3.141), Tmpy is constructed from Y () to Auto F3=std::async (Y (), 3.141),//Call Y (2.718), Auto F4=std::async (Std::ref (y), 2.718); x Baz (x&);//Call Baz (x); auto F6=std::async (Baz,std::ref (x)); Class Move_only{public: move_only (); Move_only (move_only&&); Move_only (move_only const&) = delete; move_only& operator= (move_only&&); move_only& operator= (move_only const&) = delete; void operator () ();};/ /Call TMP (); TMP is constructed from Std::move (move_only) to Auto F5=std::async (Move_only ());
By default, we need to decide for ourselves whether the Std::async is to start a new thread or to wait for the execution to synchronize when expected. We can control it by passing it to the Std::async parameter. The parameter type is std::launch:
- Std::launch::d eferred indicates that a function call is deferred until the desired wait () or get () is called.
- Std::launch::async indicates that a new thread is started to execute the function.
- Std::launch::d eferred | Std::launch::async that the behavior is controlled by specific implementations.
The Std::async mode uses a third behavior.
Start the new thread auto F6=std::async (Std::launch::async, Y (), 1.2),//When wait () or get () is called to execute auto F7=std::async (std::launch:: Deferred, Baz, Std::ref (x));//depending on implementation of auto F8=std::async (std::launch::d eferred | std::launch::async, baz, Std::ref ( x); auto F9=std::async (Baz, Std::ref (x));//Call the deferred function f7.wait ();
This is not the only way to associate a std::future with a task instance; You can also wrap the task in an std::p ackaged_task<> instance, or use std::p romise<> type template.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
[c++11 Concurrent programming] 13 use expectation wait one-time event