読者です 読者をやめる 読者になる 読者になる

Boost.Asio io_serviceを包含する設計

C++

boost::asio::io_serviceはそんなにポンポン作りたくないので、他で使ってるのを自分のクラスでも使えたらうれしいです。他で使われていない場合に自己完結できると使いやすくてさらに良いです。
cpp-netlibはboost::asio::io_serviceをoptionalに受け取れるような設計になっていて、これは普段Boost.Asioを使う上でも適用できる設計だと思うので、紹介としてここに書いておきます。

#include <boost/asio.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/bind.hpp>

namespace asio = boost::asio;

class Client : boost::noncopyable {
    boost::shared_ptr<asio::io_service> io_service_ptr_; // 初期化のためだけにある
    asio::io_service& io_service_;
    asio::deadline_timer timer_;
public:
    // io_serviceが渡されたらそれを使う
    Client(asio::io_service& io_service)
        : io_service_(io_service),
          timer_(io_service_)
    {}

    // io_serviceが渡されなかったら作る
    Client()
        : io_service_ptr_(new asio::io_service()),
          io_service_(*io_service_ptr_),
          timer_(io_service_)
    {}

    asio::io_service& get_io_service() { return io_service_; }

    // てきとーなタイマー
    void start()
    {
        timer_.expires_from_now(boost::posix_time::seconds(3));
        timer_.async_wait(boost::bind(&Client::notify, this));
    }

private:
    void notify()
    {
        std::cout << "notify" << std::endl;
    }
};

int main()
{
    // io_serviceを渡す
    {
        asio::io_service io_service;

        Client client(io_service);
        client.start();

        client.get_io_service().run();
    }

    // io_serviceを渡さない
    {
        Client client;
        client.start();

        client.get_io_service().run();
    };
}
notify
notify