The reactor is an asynchronous framework, built around a coroutine scheduler (using boost::context or libcoroutine and benefiting from boost::asio) providing cooperative multitasking on a single system thread, enabling simple and safe imperative style concurrency.
The reactor is part of the Elle set of libraries.
The reactor was designed to suit the needs of I/O bound projects. In this situation, you can benefit from near maximum CPU potential, while other coroutines are waiting on I/O. Furthermore, program behavior is highly predictable compared to parallel programming: context switches trigger when a coroutine yields, synchronization tools give strong guaranties on coroutines execution order and no code is executed in parallel (unless you explicitly ask for it, and the reactor provides tools to make both worlds (single-threading and multi-threading) coexist).
The main logic of simple echo server implementation would look like:
elle::reactor::Thread acceptor(sched, "acceptor", [&]
{
elle::reactor::network::TCPServer server;
server.listen(8080);
// Scope enable to start tasks and make sure they are terminated upon
// destruction, elle::With handles nested exceptions.
elle::With<elle::reactor::Scope>() << [&] (reactor::Scope& scope)
{
while (true)
{
// Server::accept yields until it gets a connection.
auto socket = elle::utility::move_on_copy(server.accept());
// Scope::run_background spawns a new coroutine.
scope.run_background(
elle::sprintf("client %s", socket),
[socket]
{
try
{
while (true)
{
// This coroutine, Yield until reading "<...>\n".
elle::Buffer line = socket->read_until("\n");
// Write the line we just get (this yields too).
socket->write(line);
}
}
catch (elle::reactor::network::ConnectionClosed const&)
{}
});
}
};
});
See full example.
See Elle: How to compile.
./drake //reactor/build -j 2
- Website: https://infinit.sh/open-source
- Email: [email protected]