等到发布到 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 完成,下面的代码就会运行依赖于taskAtaskB。它并行运行其中四个任务:

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++ 线程池,为啥我不能重用我的线程?

Helgrind 在简单的 boost::asio::thread_pool 程序中报告同步错误

试图等到多个图像上传到 cloudinary

等到图像加载到 angularjs 工厂中

如何等到从 Firebase 检索到我的数据? [复制]

如何等到所有商店都加载到 ExtJs 中?