30

D-Busをアプリケーションと統合しようとしていboost::asioます。

D-Busには、監視対象の一連のUnixファイル記述子(主にソケットですが、FIFOの場合もあります)を列挙するAPIがあります。それらの記述子に読み取るものがある場合は、D-Bus APIに通知して、記述子を読み取って実行できるようにする必要があります。

現在、私はこれを行っています:

using boost::asio::posix::stream_descriptor;
void read_handle(stream_descriptor* desc, const boost::system::error_code& ec,
                 std::size_t bytes_read)
{
    if (!ec) {
        stream_descriptor::bytes_readable command(true);
        descriptor->io_control(command);
        std::size_t bytes_readable = command.get();
        std::cout << "It thinks I should read" << bytes_readable
            << " bytes" << std::endl;
    } else {
        std::cout << "There was an error" << std::endl;
    }
}

void watch_descriptor(boost::asio::io_service& ios, int file_descriptor)
{
    // Create the asio representation of the descriptor
    stream_descriptor* desc = new stream_descriptor(ios);
    desc->assign(file_descriptor);

    // Try to read 0 bytes just to be informed that there is something to be read
    std::vector<char> buffer(0);
    desc->async_read_some(boost::asio::buffer(buffer, 0),
        boost::bind(read_handle, desc, _1, _2));
}

ただし、ハンドラーはすぐに呼び出され、読み取るバイト数が0であると通知されます。何か読むものがあるときだけ呼んでほしいのですが、boost::asioは読めません。それは栄光のように振る舞うべきselect()です。それを行う簡単な方法はありますか?

PS:私はboost::asio自分のソフトウェアで広く使用していますが、これはそのほんの一部にすぎないので、glib他のメインループに依存したくありません。

4

1 に答える 1

33

これはまさにnull_buffers設計された問題です。

プログラムは、I/O操作自体を実行したいサードパーティのライブラリと統合する必要がある場合があります。これを容易にするために、Boost.Asioには、読み取り操作と書き込み操作の両方で使用できるnull_buffersタイプが含まれています。null_buffers操作は、I/Oオブジェクトが操作を実行する準備ができるまで戻りません。

例として、非ブロッキング読み取りを実行するには、次のようなものを使用できます。

ip::tcp::socket socket(my_io_service);
...
ip::tcp::socket::non_blocking nb(true);
socket.io_control(nb);
...
socket.async_read_some(null_buffers(), read_handler);
...
void read_handler(boost::system::error_code ec)
{
  if (!ec)
  {
    std::vector<char> buf(socket.available());
    socket.read_some(buffer(buf));
  }
}

ドキュメントには優れた例も含まれています。

于 2011-01-13T23:32:21.280 に答える