C++ 11 provides classes and functions related to asynchronous operations. Different classes have different functions. Generally speaking, classes mainly include: STD:: future, STD:: promise, STD:: package_ The task function is mainly std::async.
1 asynchronous operation class
The main functions of the above three classes are:
- std::future: this class is mainly used as an asynchronous result transmission channel to obtain the return value of thread function;
- std::promise: used to wrap a value and bind it with futre to facilitate thread assignment;
- std::package_task: wrap a callable object and use it with future to facilitate asynchronous invocation.
1.1 std::future
The thread library provides the result of the future access asynchronous operation. Because the asynchronous result cannot be obtained immediately, it can only be obtained at some time in the future. This result is a future value, so it is called future. The results are obtained by querying the future status. Future consists of three statuses:
- Deferred: the asynchronous operation has not started yet
- Ready: the asynchronous operation has completed
- Timeout: asynchronous operation timeout
In actual coding, the execution results can be obtained asynchronously by judging these three internal states. Code examples are as follows:
std::cout << "checking, please wait"; std::chrono::milliseconds span (1000); do{ status = fut.wait_for(span); if(status == std::future_status::deferred) { std::cout << "\ndeferred" << std::flush; } else if(status == std::future_status::timeout) { std::cout << "\ntimeout" << std::flush; } else if(status == std::future_status::ready) { std::cout << "\ready" << std::flush; } }while(status != std::future_status::ready);
1.2 std::promise
Using std::promise, you can transfer values between two different threads. The method of use is as follows:
void print_set(std::promise<int> &pro) { std::cout << "set value: " << "100" << '\n'; pro.set_value(100); } void print_int (std::future<int>& fut) { int x = fut.get(); std::cout << "value: " << x << '\n'; } int main () { std::promise<int> prom; std::future<int> fut = prom.get_future(); std::thread th2 (print_set, std::ref(prom)); std::thread th1 (print_int, std::ref(fut)); th1.join(); th2.join(); return 0; }
The running results of the above code are as follows:
set value: 100 value: 100
1.3 std::package_task
Similar to std::promise, it needs to be used in combination with future, but the difference is std::package_task wraps a function to facilitate asynchronous calls. The method of use is as follows:
int Add(int x,int y) { return (x+y); } int main () { std::packaged_task<int(int,int)> pFun(Add); std::future<int> fut = pFun.get_future(); std::thread th2 (std::move(pFun), 3,2); int iRes = fut.get(); std::cout<<"iRes="<<iRes<<std::endl; th2.join(); return 0; }
The running result of the program is: iRes=5
2. Asynchronous operation function: async
Compared with the previous asynchronous operation classes, std::async is much more advanced, and you can directly create asynchronous task classes. The asynchronous return results are saved in future. When obtaining the return results of thread functions, use get() to obtain the return value. If no value is required, use wait() method.
The std::async prototype is as follows:
future<typename result_of<Fn(Args...)>::type> async (launch::async|launch::deferred, Fn&& fn, Args&&... args);
The prototype parameters are described as follows:
- launch::async: start the thread after calling async
- launch::deferred: delay starting the thread until wait and get are called later.
- fn: thread function
- args: thread function parameters
The basic usage of async is as follows:
bool is_prime (int x) { std::this_thread::sleep_for(std::chrono::seconds(3)); for (int i=2; i<x; ++i) if (x%i==0) return false; return true; } int main () { // call function asynchronously: std::future<bool> fut = std::async (is_prime,444444443); std::future_status status; // do something while waiting for function to set future: std::cout << "checking, please wait"; std::chrono::milliseconds span (1000); do{ status = fut.wait_for(span); if(status == std::future_status::deferred) { std::cout << "\ndeferred" << std::flush; } else if(status == std::future_status::timeout) { std::cout << "\ntimeout" << std::flush; } else if(status == std::future_status::ready) { std::cout << "\ready" << std::flush; } }while(status != std::future_status::ready); bool x = fut.get(); // retrieve return value std::cout << "\n444444443 " << (x?"is":"is not") << " prime.\n"; return 0; }
If the operation of the above code is:
checking, please wait "\n444444443 is prime."
Async is a higher-level asynchronous operation. In actual coding, you can easily obtain the thread execution status and results without paying attention to the details of thread creation; Generally, the launch::async parameter is used by default.