繁体   English   中英

如何检查io_service中的任务是否完成?

[英]How to check whether tasks in io_service are completed?

我对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 ,那么您不必使用{}作用域来等待任务。

io_service::run文档

run()函数将阻塞,直到所有工作都完成并且不再需要调度处理程序为止,或者直到io_context被停止为止。

另外,从io_context::work构造函数文档中

构造函数用于通知io_context一些工作已经开始。 这样可以确保io_context对象的run()函数不会在工作进行时退出

[强调我的]

简而言之,如果run函数返回,而stopped函数返回false,则说明所有工作已经完成。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM