c++ - 如何查看io_service中的任务是否完成?

标签 c++ boost concurrency boost-asio asio

我有一个关于 boost::io_service 的问题。

我有一组可以同时运行的任务。运行所有这些之后,我需要同时运行另一组任务。但是,必须在开始运行第二组之前完成第一组。这意味着我需要确保提交到 io_service 的所有作业都已完成,然后才能开始安排到第二组。

我可以通过保留某种计数器并添加一个繁忙的循环来实现它,但它看起来效率不高。所以,我想检查一下是否有人有更好的主意。以下是我用来进行实验的虚拟代码。

提前致谢!

 #include <cstdio>
 #include <iostream>
 #include <unistd.h>
 #include <boost/asio/io_service.hpp>
 #include <boost/bind.hpp>
 #include <boost/thread/thread.hpp>

 const size_t numTasks = 100000;

 void print_counter(const size_t id)
 {
   if (id + 1 == numTasks) {
     printf("sleeping for %ld\n", id);
     sleep(15);
   }
   printf("%ld\n", id);
 }

 int main(int argc, char** argv)
 {
   using namespace std;
   using namespace boost;

   asio::io_service io_service;
   asio::io_service::work work(io_service);

   const size_t numWorker = 4;
   boost::thread_group workers;
   for(size_t i = 0; i < numWorker; ++i) {
     workers.create_thread(boost::bind(&asio::io_service::run, &io_service));
   }

   for(size_t i = 0; i < numTasks; ++i) {
     io_service.post(boost::bind(print_counter, i));
   }

   // TODO: wait until all the tasks are done above


   for(size_t i = 0; i < numTasks; ++i) {
     io_service.post(boost::bind(print_counter, i));
   }

   // TODO: wait until all the tasks are done above

   // ...

   // Finally stop the service
   io_service.stop();
   workers.join_all();
   return 0;
 }

最佳答案

您的主要问题是您的所有任务集都由 io_service 的同一个实例处理。函数 io_service::run 返回没有要处理的任务的地方。 io_service::work 的析构函数通知 io_service 对象 run 可以返回队列中没有待执行任务的地方。您可以发布第一组的所有任务,然后销毁工作并等待 io_service::run 返回,然后再次创建 work 对象,发布下一组的任务并删除工作, 等等。要做到这一点,只需编写如下所示的辅助类:

class TasksWaiter 
{
public:
    TasksWaiter(int numOfThreads) 
    {
        work = std::make_unique<boost::asio::io_service::work>(io_service);
        for(size_t i = 0; i < numOfThreads; ++i) {
            workers.create_thread(boost::bind(&boost::asio::io_service::run, &io_service));
        }
    }

    ~TasksWaiter() {
        work.reset();
        workers.join_all();
    }

    template<class F>
    void post(F f) {
        io_service.post(f);
    }

    boost::thread_group workers;
    boost::asio::io_service io_service;
    std::unique_ptr<boost::asio::io_service::work> work;
};

int main()
{
    {
        TasksWaiter w1{4};
        for (int i = 0; i < numTasks; ++i)
            w1.post(boost::bind(print_counter,i));
        // work in w1 is destroyed, then io_service::run ends 
        // when there are no tasks to be performed
    }
    printf("wait here");
    {
        TasksWaiter w1{4};
        for (int i = 0; i < numTasks; ++i)
            w1.post(boost::bind(print_counter,i));
    }
}

几点说明:

  1. 在构造函数中创建线程池

  2. 在析构函数中工作被删除,因此 io_service::run 仅在没有待处理任务时返回

  3. 析构函数的功能可以包装到成员函数中 - 例如wait,那么您就不必使用 {} 范围来等待您的任务。

关于c++ - 如何查看io_service中的任务是否完成?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56352208/

相关文章:

c++ - WxWidgets 中带有累积缓冲区的 OpenGL 运动模糊

c++ - 从 boost ptime 获取年份

boost 库大小 = 10.9GB?

java - 并发 - foreach 循环中的非阻塞设计

c++ - 如何使用模板类型专门化模板函数

c++ - 倒序排序。 "Don' t 重复你自己”规则

c++ - 如何将 QList<T> 转换为 QVariant?

c++ - 使用 asio 时双重释放或损坏

java - 为什么我们必须使用相同的 volatile 字段来使用 volatile 关键字建立 happens-before 关系?

C - 多个进程写入同一个日志文件