I'm trying to integrate D-Bus with my boost::asio
application.
D-Bus has an API that enumerates a set of Unix file descriptors (mainly sockets but could also be FIFOs) to be watched. When those descriptors have something to be read I should inform the D-Bus API so it can read them and do it's thing.
Currently I'm doing this:
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)); }
But the handler is called right away saying that it has 0 bytes to be read. I would like it to be called only when there is something to be read, but boost::asio CAN NOT read it. It should act just as a glorified select()
. Is there a simple way to do that?
PS: I'm extensively using boost::asio
in my software, this is just a small part of it, so I would like not to depend on glib
or other mainloops.
This is precisely the problem null_buffers was designed for.
Sometimes a program must be integrated with a third-party library that wants to perform the I/O operations itself. To facilitate this, Boost.Asio includes a null_buffers type that can be used with both read and write operations. A null_buffers operation doesn't return until the I/O object is "ready" to perform the operation.
As an example, to perform a non-blocking read something like the following may be used:
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)); } }
There's also an excellent example included in the documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With