Why Does Boost.Asio Not Support an Event-Based Interface

boost asio asynchronously waiting on a condition variable

If I understand the intent correctly, you want to launch an event handler, when some condition variable is signaled, in context of asio thread pool? I think it would be sufficient to wait on the condition variable in the beginning of the handler, and io_service::post() itself back in the pool in the end, something of this sort:

#include <iostream>
#include <boost/asio.hpp>
#include <boost/thread.hpp>
boost::asio::io_service io;
boost::mutex mx;
boost::condition_variable cv;
void handler()
{
boost::unique_lock<boost::mutex> lk(mx);
cv.wait(lk);
std::cout << "handler awakened\n";
io.post(handler);
}
void buzzer()
{
for(;;)
{
boost::this_thread::sleep(boost::posix_time::seconds(1));
boost::lock_guard<boost::mutex> lk(mx);
cv.notify_all();
}
}
int main()
{
io.post(handler);
boost::thread bt(buzzer);
io.run();
}

boost.asio test problem

The list of all UDP socket constructors if found here. As you can see, you must provide at least a reference to a boost::asio::io_service object.

If this is a private variable, provide this reference in the class constructor's initializer list. The following will compile:

#include <boost/asio.hpp>
class Socket
{
boost::asio::ip::udp::socket socket_;
public:
Socket( boost::asio::io_service& ioserv) : socket_(ioserv) {}
};
int main()
{
boost::asio::io_service io;
Socket s(io);
}

Boost.Asio throws 'No such device' exception when trying to join multicast group

With no DHCP working, there is no route for multicast.

Use:

route add -net 224.0.0.0/4 dev eth0

Can a boost::asio::yield_context be used as a deadline_timer handler when doing cancel?

The async_wait() operation is being cancelled, resulting in the asynchronous operation failing with an error code of boost::asio::error::operation_aborted. As noted in the Stackful Coroutines documentation, when the boost::asio::yield_context detects that the asynchronous operation has failed, it converts the boost::system::error_code into a system_error exception and throws. Within the coroutine, consider either:

  • Initiating the asynchronous operation with a handler of context[error_code], causing the yield_context to populate the provided boost::system::error_code on failure rather than throwing.

    boost::system::error_code error;
    timer_.async_wait(context[error]); // On failure, populate error.
  • Catch the system_error and suppress it.


On failure Boost.Asio will populate a boost::system::error_code if the application is capable of receiving it, otherwise it will throw an exception. This pattern can be observed throughout Boost.Asio:

  • All asynchronous operation handler's accept an lvalue const boost::system::error_code as their first parameter. Hence, the initiating function should not throw, as the application will be informed of the error within the handler. This is not always apparent when using functors that discards extra arguments, such as boost::bind.
  • Synchronous operations are overloaded to support throwing and non-throwing versions. For example, timer.cancel() will throw on failure, where as timer.cancel(boost::system::error_code&) will set the error_code to indicate the error.
  • As noted above, when an asynchronous operation fails within a stackful coroutine and the yield_context handler is not provided a boost::system::error_code, then a system_error exception will be thrown.
  • When using futures, if the asynchronous operation fails, then the error_code is converted into a system_error exception and passed back to the caller through the future.

Here is a complete minimal example based on the original problem that runs to completion.

#include <boost/asio.hpp>
#include <boost/asio/spawn.hpp>

int main()
{
boost::asio::io_service io_service;
boost::asio::deadline_timer timer(io_service);
timer.expires_from_now(boost::posix_time::pos_infin);

boost::asio::spawn(io_service,
[&](boost::asio::yield_context yield)
{
// As only one thread is processing the io_service, the posted
// timer cancel will only be invoked once the coroutine yields.
io_service.post([&](){ timer.cancel(); });

// Initiate an asynchronous operation, suspending the current coroutine,
// and allowing the io_service to process other work (i.e. cancel the
// timer). When the timer is cancelled, the asynchronous operation is
// completed with an error, causing the coroutine to resume. As an
// error_code is provided, the operation will not throw on failure.
boost::system::error_code error;
timer.async_wait(yield[error]);
assert(error == boost::asio::error::operation_aborted);
});

io_service.run();
}

XMPP library working with Boost.ASIO

According some fragments of source code, Swiften uses Boost internally, but not ASIO part of it. It uses things like shared_ptr, boost::bind, random generator and so on, but not the boost::asio.

And according to sources, Swift::EventLoop has io_service-like interface, but not use it.

So the answer is: no, you cannot extract io_service from Swiften since it do not use boost::asio.

UPD: But, you can use Swiften in separate thread in async manner and then do io_service::post to your own eventloop, but need to write our own wrapper, completion handlers and so on to manage this.



Related Topics



Leave a reply



Submit