本篇内容主要讲解“C++ Futures与Promises线程如何使用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C++ Futures与Promises线程如何使用”吧!
一、说明
Futures 和 Promises 是将数据从一个线程传递到另一个线程的工具。虽然这也可以通过其他功能来完成,例如全局变量、futures 和 promises 在没有它们的情况下也能工作。此外,您不需要自己处理同步。
未来是一个从另一个线程接收值的变量。如果您访问未来以获取值,您可能需要等到其他线程提供该值。 Boost.Thread 提供 boost::future 来定义未来。该类定义了一个成员函数 get() 来获取值。 get() 是一个阻塞函数,可能需要等待另一个线程。
要在未来设置一个值,您需要使用一个承诺,因为 boost::future 不提供成员函数来设置一个值。
二、示例
Boost.Thread 提供类 boost::promise,它有一个成员函数 set_value()。您总是将 future 和 promise 成对使用。您可以使用 get_future() 从承诺中获得未来。您可以在不同的线程中使用未来和承诺。如果在一个线程中的 promise 中设置了一个值,则可以在另一个线程中从 future 中获取它。
示例 44.14。使用 boost::future 和 boost::promise
#define BOOST_THREAD_PROVIDES_FUTURE#include <boost/thread.hpp>#include <boost/thread/future.hpp>#include <functional>#include <iostream>void accumulate(boost::promise<int> &p){ int sum = 0; for (int i = 0; i < 5; ++i) sum += i; p.set_value(sum);}int main(){ boost::promise<int> p; boost::future<int> f = p.get_future(); boost::thread t{accumulate, std::ref(p)}; std::cout << f.get() << '\n';}
Example44.14
示例使用未来和承诺。未来 f 是从承诺 p 中接收到的。然后将对 promise 的引用传递给执行 accumulate() 函数的线程 t。 accumulate() 计算 0 到 5 之间所有数字的总和并将其保存在 promise 中。在 main() get() 中调用 future 将总数写入标准输出。
未来 f 和承诺 p 是相关联的。当对未来调用 get() 时,将返回使用 set_value() 存储在承诺中的值。因为该示例使用两个线程,所以可能会在 accumulate() 调用 set_value() 之前在 main() 中调用 get()。在这种情况下,get() 会阻塞,直到使用 set_value() 将一个值存储在 promise 中。
示例 44.14 显示 10。
accumulate() 必须调整为在线程中执行。它必须采用 boost::promise 类型的参数并将结果存储在其中。示例 44.15 引入了 boost::packaged_task,这是一个将值从任何函数转发到未来的类,只要该函数通过 return 返回结果即可。
示例 44.15。使用 boost::packaged_task
#define BOOST_THREAD_PROVIDES_FUTURE#include <boost/thread.hpp>#include <boost/thread/future.hpp>#include <utility>#include <iostream>int accumulate(){ int sum = 0; for (int i = 0; i < 5; ++i) sum += i; return sum;}int main(){ boost::packaged_task<int> task{accumulate}; boost::future<int> f = task.get_future(); boost::thread t{std::move(task)}; std::cout << f.get() << '\n';}
Example44.15
示例 44.15 与前一个类似,但这次没有使用 boost::promise。相反,此示例使用类 boost::packaged_task,它与 boost::promise 一样提供返回未来的成员函数 get_future()。
boost::packaged_task 的构造函数期望将在线程中执行的函数作为参数,但 boost::packaged_task 本身并不启动线程。必须将类型为 boost::packaged_task 的对象传递给 boost::thread 的构造函数,以便在新线程中执行该函数。
boost::packaged_task 的优点是它在未来存储函数的返回值。你不需要调整一个函数来在未来存储它的值。 boost::packaged_task 可以看作是一个适配器,它可以存储未来任何函数的返回值。
虽然该示例摆脱了 boost::promise,但以下示例也没有使用 boost::packaged_task 和 boost::thread。
示例 44.16。使用 boost::async()
#define BOOST_THREAD_PROVIDES_FUTURE#include <boost/thread.hpp>#include <boost/thread/future.hpp>#include <iostream>int accumulate(){ int sum = 0; for (int i = 0; i < 5; ++i) sum += i; return sum;}int main(){ boost::future<int> f = boost::async(accumulate); std::cout << f.get() << '\n';}
在示例 44.16 中,accumulate() 被传递给函数 boost::async()。这个函数统一了 boost::packaged_task 和 boost::thread。它在新线程中启动 accumulate() 并返回未来。
可以将启动策略传递给 boost::async()。这个附加参数决定了 boost::async() 是在新线程中还是在当前线程中执行该函数。如果您传递 boost::launch::async,boost::async() 将启动一个新线程;这是默认行为。如果您传递 boost::launch::deferred,该函数将在调用 get() 时在当前线程中执行。
尽管 Boost 1.56.0 允许将 boost::launch::async 或 boost::launch::deferred 传递给 boost::async(),但尚未实现在当前线程中执行函数。如果您传递 boost::launch::deferred,程序将终止。
到此,相信大家对“C++ Futures与Promises线程如何使用”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!