boost :: asio异步条件

时间:2012-07-09 23:32:43

标签: c++ multithreading boost boost-asio

这个想法是能够在消费者/生产者问题上用boost :: asio和线程池替换多线程代码。目前,每个消费者线程等待boost::condition_variable - 当生产者向队列添加内容时,它会调用notify_one / notify_all来通知所有消费者。现在当你(可能)拥有1k +消费者时会发生什么?线程不会扩展!

我决定使用boost::asio,但后来遇到了它没有条件变量的事实。然后async_condition_variable诞生了:

class async_condition_variable
{
private:
    boost::asio::io_service& service_;
    typedef boost::function<void ()> async_handler;
    std::queue<async_handler> waiters_;

public:
    async_condition_variable(boost::asio::io_service& service) : service_(service)
    {
    }

    void async_wait(async_handler handler)
    {
        waiters_.push(handler);
    }

    void notify_one()
    {
        service_.post(waiters_.front());
        waiters_.pop();
    }

    void notify_all()
    {
        while (!waiters_.empty()) {
            notify_one();
        }
    }
};

基本上,每个消费者都会拨打async_condition_variable::wait(...)。然后,制作人最终会调用async_condition_variable::notify_one()async_condition_variable::notify_all()。将调用每个消费者的句柄,并根据条件采取行动或再次致电async_condition_variable::wait(...)。这是可行的还是我在这里疯了?应该执行什么样的锁定(互斥),因为这将在线程池上运行?

P.S。:是的,这更像是一个RFC(征求意见)而不是一个问题:)。

3 个答案:

答案 0 :(得分:3)

列出事件发生时需要完成的事项。具有向该列表添加内容的功能以及从该列表中删除内容的功能。然后,当事件发生时,让一个线程池在现在需要完成的作业列表上工作。您不需要专门等待事件的线程。

答案 1 :(得分:1)

Boost :: asio可能有点难以理解。至少,我很难做到这一点。

您不需要让线程等待任何事情。当他们没有任何工作要做时,他们会自己做。似乎看起来像你想要做的那些例子已经将工作发布到每个项目的io_service。

以下代码的灵感来自this link。它实际上打开了我的眼睛,你可以用它做很多事情。

我确信这不是完美的,但我认为它给出了一般的想法。我希望这会有所帮助。

代码

#include <iostream>
#include <boost/thread.hpp>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
class ServerProcessor
{
protected:
    void handleWork1(WorkObject1* work)
    {
        //The code to do task 1 goes in here
    }
    void handleWork2(WorkObject2* work)
    {
        //The code to do task 2 goes in here
    }

    boost::thread_group worker_threads_;

    boost::asio::io_service io_service_;
    //This is used to keep io_service from running out of work and exiting to soon.
    boost::shared_ptr<boost::asio::io_service::work> work_;


public:
    void start(int numberOfThreads)
    {
        boost::shared_ptr<boost::asio::io_service::work> myWork(new boost::asio::io_service::work(io_service_));
        work_=myWork;

        for (int x=0; x < numberOfThreads; ++x)
            worker_threads_.create_thread( boost::bind( &ServerProcessor::threadAction, this ) );

    }

    void doWork1(WorkObject1* work)
    {
        io_service_.post(boost::bind(&ServerProcessor::handleWork1, this, work));
    }

    void doWork2(WorkObject2* work)
    {
        io_service_.post(boost::bind(&ServerProcessor::handleWork2, this, work));
    }


    void threadAction()
    {
        io_service_.run();
    }

    void stop()
    {
        work_.reset();
        io_service_.stop();
        worker_threads_.join_all();
    }

};

int main()
{
    ServerProcessor s;

    std::string input;
    std::cout<<"Press f to stop"<<std::endl;

    s.start(8);

    std::cin>>input;

    s.stop();

    return 0;
}

答案 2 :(得分:0)

如何使用boost :: signals2?

它是一个线程安全的boost :: signals分支,它允许你的客户端订阅回调信号以便发出。

然后,当在io_service调度作业中异步发出信号时,将执行所有已注册的回调(在发出信号的同一线程上)。