Skip to content

Latest commit

 

History

History
40 lines (28 loc) · 3.24 KB

README.md

File metadata and controls

40 lines (28 loc) · 3.24 KB

MASIO - Monadic Boost.Asio

Boost.Asio is a wonderful library in that it provides a unified API across different platforms and that this API frees developers from thinking in terms of threads, locks and alike. That said, after working with the library for some time, one realizes that there are certain code patterns that have to be repeated each time an asynchronous action is invoked.

There are three of these patterns, and as it turns out, each can be modelled with a Monad. The first and most obvious pattern is error handling - each async action has a completion handler whose first argument is an error code indicating the status of completion. The monad corresponding to handling errors is of course the Error (called result in masio) monad which contains either the result of the previous computation or an error value.

The second, perhaps not that obvious pattern is that of canceling asynchronous actions. When such action is canceled, say by closing its corresponding socket, the handler should receive an operation_aborted error code. But this is not always the case. When an async action is finished, its handler is not executed directly. Instead, the handler, together with completion status is pushed into a queue and scheduled for later execution. If the action is canceled during this period, the completion status won't change. Thus we need to keep track about whether the action has been canceled and handle such situation inside the callback handler. Such pattern is nicely modeled with the Reader monad.

The last one is the Continuation Passing Style pattern which can be modeled using the Continuation monad.

One of the nice things about monads is that they can be composed together using monad transformers. And the composition of the above mentioned monads is what Masio is trying to accomplish. In particular, masio::action is (loosely) isomorphic to the monad

data Action a = ReaderT (IORef State) (ErrorT (ContT IO)) a

Basic usage

io_service ios;
tcp::ip::socket socket(ios);

auto program = resolve(ios, host_string, port_string)
            >= [&](tcp::resolver::iterator iterator) {
                 return connect(socket, iterator);
               }
            >= [&]() {
                 // Send and receive 'at the same time'.
                 // If one fails, cancel the other.
                 return all_or_none( receive(socket, buffer(...))
                                   , send(socket, buffer(...)));
               };

program.execute([](result<> r) {
  ... // The action ended, handle it here.
  });

ios.run();    

Chat client

The chat_client example is a Masio implemetation of the equaly named chat_client from the examples provided on the Boost.Asio page (it works with the server).