Boost.Asioでio_service::run()を包含する設計

Boost.Asio io_serviceを包含する設計 - Faith and Brave - C++で遊ぼう
上の話に加えて、io_service::run()を誰が呼ぶかという話についてのメモ。
1つは上で紹介されているように、io_serviceを公開し、ユーザーにrun()させるパターン。

class client
{
public:
    client()
      : m_io_service(new boost::asio::io_service())
    {}

    explicit client(boost::asio::io_service &io_service)
      : m_io_service(&io_service, [](boost::asio::io_service *) {})
    {}

    boost::asio::io_service &get_io_service() const noexcept
    {
        return *m_io_service;
    }

    void start()
    {
        // ...
    }

private:
    std::shared_ptr<boost::asio::io_service> m_io_service;
};

void f()
{
    client client_;
    client_.start();
    client_.get_io_service().run();
}

もう1つはcpp-netlibがそうしているように、自分がio_serviceを作った場合は自分でrun()するパターン。

class client
{
public:
    client()
      : m_io_service(new boost::asio::io_service()),
        // run()がすぐ終了しないよう、workを注入する
        m_work(new boost::asio::io_service(*m_io_service)),
        // スレッドを立ててrun()を呼び出す
        m_thread([=] { m_io_service->run(); })
    {}

    explicit client(boost::asio::io_service &io_service)
      : m_io_service(&io_service, [](boost::asio::io_service *) {})
    {}

    ~client()
    {
        if (m_work)
        {
            cancel();
            // workを削除して、run()が終了できるようにする
            m_work.reset();
            // run()の終了を待つ
            m_thread.join();
        }
    }

    void start()
    {
        // ...
    }

private:
    std::shared_ptr<boost::asio::io_service> m_io_service;
    std::unique_ptr<boost::asio::io_service::work> m_work;
    std::thread m_thread;
};

どちらを使うかはお好みです。
なお個人的には常にio_serviceを渡してもらえばいいと思っているもよう。