等到发布到 boost::asio::thread_pool 的作业(与所有作业完全相反)完成?
Posted
技术标签:
【中文标题】等到发布到 boost::asio::thread_pool 的作业(与所有作业完全相反)完成?【英文标题】:Wait until A job (as starkly opposed to ALL jobs) posted to boost::asio::thread_pool completes? 【发布时间】:2021-08-05 15:02:12 【问题描述】:我将多个职位发布到 boost::asio::thread_pool
,并且我想在每个结果可用后立即处理他们的结果。我会 1000 倍更喜欢这个“事件循环”习惯用语而不是回调习惯用语,因为事件循环习惯用语会自动为我进行同步:只有一个线程使用结果并将它们写入聚合数据结构,而无需同步访问它。文档不清楚如何执行此操作;给出的示例使用了许多困难的概念,并且看起来比事件循环惯用语的典型实例要复杂 10 倍左右。
boost::asio
是否完全支持事件循环习语?
【问题讨论】:
【参考方案1】:Asio 有前摄器模型。基本上,服务通过在准备好时执行新的处理程序来“运行”。如果您将处理程序视为事件,那么您将看到您已经拥有了您所追求的。
池在每个线程的事件循环上运行。因此,您有一个任务,并让它将延续事件发布到池中。与您描述的保证相同。
演示
只要taskA
完成,下面的代码就会运行依赖于taskA
的taskB
。它并行运行其中四个任务:
Live On Coliru
// #define BOOST_ASIO_ENABLE_HANDLER_TRACKING
#include <boost/asio.hpp>
#include <random>
#include <iostream>
#include <iomanip>
using namespace std::literals;
auto now = std::chrono::high_resolution_clock::now;
static auto const start = now();
static void randelay()
thread_local auto gen = std::bind(std::uniform_int_distribution<>(100, 800),
std::mt19937std::random_device());
std::this_thread::sleep_for(gen() * 1ms);
int main()
auto taskB = [](int resultFromTaskA)
randelay();
static std::mutex mx;
std::lock_guard lk(mx);
std::cout << "at " << std::setw(4) << (now() - start) / 1ms
<< "ms taskB resultFromTaskA: " << resultFromTaskA
<< std::endl;
;
boost::asio::thread_pool ctx;
auto executor = ctx.get_executor();
auto taskA = [=](int payload)
randelay();
post(executor, std::bind(taskB, payload*payload));
;
for (auto i = 1; i < 5; ++i)
post(ctx, std::bind(taskA, i));
ctx.join();
打印例如
at 234ms taskB resultFromTaskA: 16
at 837ms taskB resultFromTaskA: 4
at 1214ms taskB resultFromTaskA: 1
at 1290ms taskB resultFromTaskA: 9
并启用处理程序跟踪:
【讨论】:
是的,我在示例中看到过这样的代码,而我正在寻找更好的东西的原因是因为它既复杂又丑陋。最丑陋的部分是生产者需要知道消费者,但显式同步的需要也很讨厌。 不需要显式同步。我添加的唯一同步是保护 std::cout。基于事件的解决方案如何让事情变得更好?你不能将延续(“消费者”)传递给生产者吗?如果您遵循异步启动协议,您甚至可以将其与期货、协程内部、co_await 等一起使用。 如果您认为事件使解耦变得更好,那么是什么阻止您将事件推入(无锁?)队列并使用它?我敢打赌,您会达到 catch-22,因为您必须以一种或另一种方式在队列上同步。这就是事件的本质。 哦,另外一件事,你没有问过类似屏障的语义,但也许看看***.com/questions/61328430/…以上是关于等到发布到 boost::asio::thread_pool 的作业(与所有作业完全相反)完成?的主要内容,如果未能解决你的问题,请参考以下文章
使用 boost::asio::thread_pool 的 C++ 线程池,为啥我不能重用我的线程?