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

Boost.Asio Reactorスタイル

C++

Boost.Asioは、Proactorパターンのスタイルの他に、Reactorパターンのスタイルもサポートしています。
以下、Reactorスタイルの例:

#include <iostream>
#include <vector>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/range/algorithm/for_each.hpp>

namespace asio = boost::asio;

class Client {
    asio::io_service& io_service_;
    asio::ip::tcp::socket socket_;

public:
    Client(asio::io_service& io)
        : io_service_(io), socket_(io) {}

    void connect()
    {
        namespace ip = asio::ip;
        socket_.connect(ip::tcp::endpoint(
                            ip::address::from_string("127.0.0.1"), 31400));
    }

    void start_read()
    {
        socket_.non_blocking(true);
        socket_.async_read_some(
            asio::null_buffers(),
            boost::bind(&Client::read_handler, this, _1));
    }

private:
    void read_handler(const boost::system::error_code& error)
    {
        if (error) {
            std::cout << "Error: " << error.message() << std::endl;
            return;
        }

        std::vector<char> buf(socket_.available());
        socket_.read_some(asio::buffer(buf));

        std::cout << std::string(buf.begin(), buf.end()) << std::endl;
    }
};


int main()
{
    asio::io_service io_service;
    Client client(io_service);

    client.connect();
    client.start_read();

    io_service.run();
}

Proactorスタイルでは、非同期関数を実行する際にバッファへの参照を渡し、完了ハンドラでバッファを参照しますが、Reactorスタイルでは、非同期関数に渡すハンドラが「準備ができたら呼ばれる関数」を意味するようになり、ハンドラ内で同期関数を改めて呼び出し、準備ができた分だけ処理します。


参照:
Reactor-Style Operations - Boost Asio Library