简体   繁体   English

使用Boost Asio的C ++线程

[英]C++ threading with boost asio

I have a thread pool using boosts library's and I have set up in the example below running two threads that get re-run 4 times. 我有一个使用boosts库的线程池,并且在下面的示例中设置了运行两个线程,并重新运行4次。 What is the best way that I can check is_service to see if all child threads execution are finished, before I can move on in the code? 在可以继续执行代码之前,检查is_service以查看所有子线程执行是否完成的最佳方法是什么? the rest of the code depends on all the child threads finishing before the program can move on. 其余代码取决于程序继续运行之前所有子线程完成。 I can get the desired behavior if I put a Sleep(1000) call but this is undesirable, I have looked at a check on io_service_.stopped() but always returns a 0 . 如果我进行Sleep(1000)调用,则可以得到所需的行为,但这是不希望的,我查看了io_service_.stopped()的检查,但始终返回0 Any thoughts would be greatly appreciated. 任何想法将不胜感激。

#include <iostream>                   
#include <boost/asio/io_service.hpp>
#include <boost/bind.hpp>
#include <boost/thread/thread.hpp>
#include <vector>               
#include <string>

using namespace std;

class Model {
  public:
    // Constructor
    Model() {
        work_ctrl_ = new boost::asio::io_service::work(io_service_);

        for (int i = 0; i < 2; ++i) {
            threads_.create_thread(
                    boost::bind(&boost::asio::io_service::run, &io_service_));
        }
    }
    // Deconstructor
    ~Model() {
        delete work_ctrl_;
    }

    // Function I want to thread
    void manipulate_vector(unsigned start, unsigned last) {
        cout << "entering manipulate vector(), from thread " << boost::this_thread::get_id() << endl;
        for(unsigned k = start; k <= last; ++k)
            my_vector_[k] *= sqrt(32);
        cout << "exit manipulate vector()" << endl;
        Sleep(500); // Add a sleep to mimic a long algorithm being executed
    }

    void update() {
        // Do otherstuff that can't be threaded
        cout << "entering update" << endl;

        // run manipulate_vector() across multiple threads
        // - start thread
        // - execute function call.
        // - stop thread
        io_service_.post(boost::bind(manipulate_vector, this, 0, mid_point_));
        io_service_.post(boost::bind(manipulate_vector, this, mid_point_, my_vector_.size()));

        cout << io_service_.stopped() << endl;

        // keep doing otherstuff that can't be threaded
        cout << "hopefully the threads are finished and I can take that information and continue." << endl;
    }

    void run(void) {
        // call update 10 times
        for(unsigned i = 0; i < 4; ++i) {
            update();
            //Sleep(2000);
        }
    }

    void initialise() {
        // initialise vector
        for(unsigned j = 0; j < 100000000; ++j)
            my_vector_.push_back(j);
        mid_point_ = 49999999;
    }

  private:
    boost::asio::io_service io_service_;
    boost::thread_group threads_;
    boost::asio::io_service::work *work_ctrl_;
    unsigned n_threads_;
    vector<double>  my_vector_;
    unsigned mid_point_;
};

int main() {
    std::cout << "----------Enter Main----------" << std::endl;
    Model model;
    model.initialise();
    model.run();
    std::cout << "----------Exit Main----------" << std::endl;
    system("PAUSE");
}

Presumably you want to know when your work is complete rather than when the threads stop executing (they won't until you call io_service.stop() or delete work-ctrl_ ). 大概您想知道工作何时完成,而不是线程何时停止执行(直到您调用io_service.stop()或删除work-ctrl_时,它们才work-ctrl_ )。

The standard solution is to use a condition variable: 标准解决方案是使用条件变量:

std::mutex mutex;
std::condition_variable condition;
int workCount;

void manipulate_vector(unsigned start, unsigned last) {
    cout << "entering manipulate vector(), from thread " << boost::this_thread::get_id() << endl;
    for(unsigned k = start; k <= last; ++k)
        my_vector_[k] *= sqrt(32);
    cout << "exit manipulate vector()" << endl;
    Sleep(500); // Add a sleep to mimic a long algorithm being executed
    std::unique_lock<std::mutex> lock(mutex);
    workCount--;
    condition.notify_one();
}

void update() {
    // Do otherstuff that can't be threaded
    cout << "entering update" << endl;

    // run manipulate_vector() across multiple threads
    // - start thread
    // - execute function call.
    // - stop thread
    workCount = 2;
    io_service_.post(boost::bind(manipulate_vector, this, 0, mid_point_));
    io_service_.post(boost::bind(manipulate_vector, this, mid_point_, my_vector_.size()));
    {
       std::unique_lock<std::mutex> lock(mutex);
       condition.wait(lock, [&]{ return workCount == 0; });
    }
}

If you are OK with some of the work being run in the current thread, you can call io_service_.run() where you want to wait after deleting work_ctrl_ . 如果您对当前线程中正在运行的某些工作没问题,可以在删除work_ctrl_之后调用io_service_.run()来等待。 When it returns there is no work left and you can safely proceed. 当它返回时,没有工作了,您可以安全地继续。 You could reduce your level of concurrency in the thread group by one to get the same overall concurrency. 您可以将线程组中的并发级别降低一级,以获取相同的整体并发性。

A simple alternative is simply to call threads_.join_all() after all the posts have been queued and you have deleted work_ctrl_ . 一种简单的替代方法是在所有帖子都排队并且删除了work_ctrl_之后,简单地调用threads_.join_all()

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

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