/* * @Author: your name * @Date: 2021-01-25 11:16:44 * @LastEditTime: 2021-01-29 17:44:42 * @LastEditors: Please set LastEditors * @Description: In User Settings Edit * @FilePath: /myCOde/app/future.cpp */ #include <iostream> #include <thread> #include <algorithm> #include <vector> #include <list> #include <mutex> #include <future> //引入std::future头文件 using namespace std;
int test_async_1() { auto is_prime = [](int x) { std::cout << "Calculating. Please, wait...\n"; for (int i = 2; i < x; ++i) if (x%i == 0) return false; return true; };
// call is_prime(313222313) asynchronously: std::future<bool> fut = std::async(is_prime, 313222313); //执行这一句的时候就已经开始调用函数了 std::this_thread::sleep_for(std::chrono::milliseconds(2000)); std::cout << "Checking whether 313222313 is prime.\n"; // ...
bool ret = fut.get(); // waits for is_prime to return if (ret) std::cout << "It is prime!\n"; else std::cout << "It is not prime.\n";
return 0; }
int test_async_2() { auto print_ten = [](char c, int ms) { for (int i = 0; i < 10; ++i) { std::this_thread::sleep_for(std::chrono::milliseconds(ms)); std::cout << c; } };
std::cout << "with launch::async:\n"; std::future<void> foo = std::async(std::launch::async, print_ten, '*', 100); std::future<void> bar = std::async(std::launch::async, print_ten, '@', 200); // async "get" (wait for foo and bar to be ready): foo.get(); // 注:注释掉此句,也会输出'*' bar.get(); std::cout << "\n\n"; std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::cout << "with launch::deferred:\n"; foo = std::async(std::launch::deferred, print_ten, '*', 100); bar = std::async(std::launch::deferred, print_ten, '@', 200); // deferred "get" (perform the actual calls): //foo.get(); // 注:注释掉此句,则不会输出'**********' //bar.get(); std::cout << '\n';
return 0; }
std::mutex m;
struct X { void foo(int i, const std::string& str) { std::lock_guard<std::mutex> lk(m); std::cout << str << ' ' << i << '\n'; } void bar(const std::string& str) { std::lock_guard<std::mutex> lk(m); std::cout << str << '\n'; } int operator()(int i) { std::lock_guard<std::mutex> lk(m); std::cout << i << '\n'; return i + 10; } };
int test_async_3() { X x; // Calls (&x)->foo(42, "Hello") with default policy: // may print "Hello 42" concurrently or defer execution auto a1 = std::async(&X::foo, &x, 42, "Hello"); // Calls x.bar("world!") with deferred policy // prints "world!" when a2.get() or a2.wait() is called auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!"); // Calls X()(43); with async policy // prints "43" concurrently auto a3 = std::async(std::launch::async, X(), 43); a2.wait(); // prints "world!" std::cout << a3.get() << '\n'; // prints "53"
return 0; } //
int main(){ test_async_1(); test_async_2(); return 0; }
get_future函数:(1).返回一个与promise对象的共享状态关联的std::future对象。(2).一旦准备就绪,返回的std::future对象就可以访问promise对象在共享状态上设置的值或异常。(3).每个promise共享状态只能被一个std::future对象检索(Only one future object can be retrieved for each promise shared state)。(4).调用此函数后,promise应在某个时候使其共享状态准备就绪(通过设置值或异常),否则将在销毁时自动准备就绪并包含一个std::future_error类型的异常。
operator=:(1).禁用拷贝赋值。(2).支持移动赋值。
set_exception:将异常指针存储进共享状态即设置共享状态的异常指针,准备就绪。
set_exception_at_thread_exit:设置共享状态的异常指针,但并不将该共享状态的标志设置为ready,当线程退出时,该promise对象会自动设置为ready (Stores the exception pointer p in the shared state without making it ready immediately. Instead, it will be made ready automatically at thread exit, once all objects of thread storage duration have been destroyed)。
set_value_at_thread_exit:设置共享状态的值,但并不将该共享状态的标志设置为ready,当线程退出时,该promise对象会自动设置为ready(Stores val as the value in the shared state without making it ready immediately. Instead, it will be made ready automatically at thread exit, once all objects of thread storage duration have been destroyed)。
std::future<int> fut = bar.get_future(); // engagement with future auto print_int = [&fut]() { int x = fut.get(); fprintf(stdout, "value: %d\n", x); }; std::thread th1(print_int); // send future to new thread std::this_thread::sleep_for(std::chrono::milliseconds(1000)); cout << "set value ... " << endl; bar.set_value(10); cout << "set value over " << endl; th1.join(); } { std::promise<int> prom; std::future<int> fut = prom.get_future();
auto get_int = [&prom]() { int x; std::cout << "Please, enter an integer value: "; std::cin.exceptions(std::ios::failbit); // throw on failbit try { std::cin >> x; // sets failbit if input is not int prom.set_value(x); } catch (std::exception&) { prom.set_exception(std::current_exception()); } };
auto print_int = [&fut]() { try { int x = fut.get(); std::cout << "value: " << x << '\n'; } catch (std::exception& e) { std::cout << "[exception caught: " << e.what() << "]\n"; } };
//这里已经传引用 void myAccumulate(std::vector<int>::iterator first, std::vector<int>::iterator last, std::promise<int> accumulate_promise) { int sum = std::accumulate(first, last, 0); accumulate_promise.set_value(sum); // Notify future }
// Demonstrate using promise<void> to signal state between threads. cout << "run to this " << endl; std::promise<void> barrier; std::future<void> barrier_future = barrier.get_future(); std::thread new_work_thread(do_work, std::move(barrier)); barrier_future.wait(); new_work_thread.join(); }
void test_peomise_3(){ std::promise<int> p; std::future<int> f = p.get_future();
std::thread([&p] { std::this_thread::sleep_for(1s); p.set_value_at_thread_exit(9); // gcc 4.9 don't support this function }).detach();
C++11中的std::packaged_task是个模板类。std::packaged_task包装任何可调用目标(函数、lambda表达式、bind表达式、函数对象)以便它可以被异步调用。它的返回值或抛出的异常被存储于能通过std::future对象访问的共享状态中。 std::packaged_task类似于std::function,但是会自动将其结果传递给std::future对象。 std::packaged_task对象内部包含两个元素:(1).存储的任务(stored task)是一些可调用的对象(例如函数指针、成员或函数对象的指针)( A stored task, which is some callable object (such as a function pointer, pointer to member or function object))。(2).共享状态,它可以存储调用存储的任务(stored task)的结果,并可以通过std::future进行异步访问(A shared state, which is able to store the results of calling the stored task and be accessed asynchronously through a future)。 通过调用std::packaged_task的get_future成员将共享状态与std::future对象关联。调用之后,两个对象共享相同的共享状态:(1).std::packaged_task对象是异步提供程序(asynchronous provider),应通过调用存储的任务(stored task)在某个时刻将共享状态设置为就绪。(2).std::future对象是一个异步返回对象,可以检索共享状态的值,并在必要时等待其准备就绪。 共享状态的生存期至少要持续到与之关联的最后一个对象释放或销毁为止。 std::packaged_task不会自己启动,你必须调用它(A packaged_task won’t start on it’s own, you have to invoke it)。 模板类std::packaged_task成员函数包括:
构造函数:(1).默认构造函数:无共享状态无存储任务(no shared state and no stored task)情况下初始化对象。(2). initialization constructor:该对象具有共享状态,且其存储的任务由fn初始化。(3). initialization constructor with allocator。(4).禁用拷贝构造。(5).支持移动构造。
get_future函数:(1).返回一个与packaged_task对象的共享状态关联的std::future对象。(2).一旦存储的任务被调用,返回的std::future对象就可以访问packaged_task对象在共享状态上设置的值或异常。(3).每个packaged_task共享状态只能被一个std::future对象检索(Only one future object can be retrieved for each packaged_task shared state)。(4).调用此函数后,packaged_task应在某个时候使其共享状态准备就绪(通过调用其存储的任务),否则将在销毁后自动准备就绪并包含一个std::future_error类型的异常。
reset函数:(1).在保持相同存储的任务的同时,以新的共享状态重置对象。(2).允许再次调用存储的任务。(3).与对象关联的之前的共享状态被放弃(就像packaged_task被销毁了一样)。(4).在内部,该函数的行为就像是移动赋值了一个新构造的packaged_task一样(Internally, the function behaves as if move-assigned a newly constructed packaged_task (with its stored task as argument))。
std::future<int> fut = tsk.get_future(); tsk(33); std::cout << "The triple of 33 is " << fut.get() << ".\n";
// re-use same task object: tsk.reset(); fut = tsk.get_future(); std::thread(std::move(tsk), 99).detach(); std::cout << "Thre triple of 99 is " << fut.get() << ".\n"; } { auto countdown = [](int from, int to) { for (int i = from; i != to; --i) { std::cout << i << '\n'; std::this_thread::sleep_for(std::chrono::seconds(1)); } std::cout << "Lift off!\n"; return from - to; };
std::packaged_task<int(int, int)> tsk(countdown); // set up packaged_task std::future<int> ret = tsk.get_future(); // get future
std::thread th(std::move(tsk), 5, 0); // spawn thread to count down from 5 to 0
int value = ret.get(); // wait for the task to finish and get result std::cout << "The countdown lasted for " << value << " seconds.\n";
th.join(); } }
int test_packaged_task_2() { { // lambda std::packaged_task<int(int, int)> task([](int a, int b) { return std::pow(a, b);}); std::future<int> result = task.get_future();
struct DBDataFetcher { std::string operator()(std::string token) { // Do some stuff to fetch the data std::string data = "Data From " + token; return data; } };
//使用仿函数 int test_packaged_task_3() { // Create a packaged_task<> that encapsulated a Function Object std::packaged_task<std::string(std::string)> task(std::move(DBDataFetcher()));
// Fetch the associated future<> from packaged_task<> std::future<std::string> result = task.get_future();
// Pass the packaged_task to thread to run asynchronously std::thread th(std::move(task), "Arg");
// Join the thread. Its blocking and returns when thread is finished. th.join();
// Fetch the result of packaged_task<> i.e. value returned by getDataFromDB() std::string data = result.get(); std::cout << data << std::endl;
return 0; }
int test_packaged_task_4() { // sleeps for one second and returns 1 auto sleep = []() { // // for(int i = 0; i < 1000; i++){ // // cout << "packaged task ----------" << i << endl; // // } // std::this_thread::sleep_for(std::chrono::seconds(100)); return 1; };
{ // std::packaged_task // >>>>> A packaged_task won't start on it's own, you have to invoke it std::packaged_task<int()> task(sleep);
auto f = task.get_future(); task(); // invoke the function for(int i = 0; i < 1000; i++){ cout << "main -----------" << i << endl; } // You have to wait until task returns. Since task calls sleep // you will have to wait at least 1 second. std::cout << "You can see this after 1 second\n";
// However, f.get() will be available, since task has already finished. std::cout << f.get() << std::endl; }
{ // std::async // >>>>> On the other hand, std::async with launch::async will try to run the task in a different thread : auto f = std::async(std::launch::async, sleep); std::cout << "You can see this immediately!\n";
// However, the value of the future will be available after sleep has finished // so f.get() can block up to 1 second. std::cout << f.get() << "This will be shown after a second!\n"; }
return 0; }
int main(){ // test_packaged_task_1(); test_packaged_task_4(); return 0; }