Tutorial » Promisify functions

Explains how to promisify callback taking functions into a continuable_base.

Promisification and continuables

The promisification has a longer history in the JavaScript world where the legacy way of asynchronous programming was the usage of callbacks of the form function(error, result...). The ideal way of dealing with such an asynchronous result is to return a promise and soon utility helpers were provided to do so.

The usage of callbacks to represent an asynchronous result is still a popular way nowadays. Thus the library provides the promisify helper class which makes it possible to convert callback taking functions of various styles into one that returns a continuable_base instead.

Promisify boost::asio

The default callback style is something like function(error, result...) as described above. Continuable offers the promisify::from method for such callback styles.

See an example of how to promisify boost asio's async_resolve below:

auto async_resolve(std::string host, std::string service) {
  return cti::promisify<asio::ip::udp::resolver::iterator>::from(
      [&](auto&&... args) {
        resolver_.async_resolve(std::forward<decltype(args)>(args)...);
      },
      std::move(host), std::move(service));
}

Then it should be possible to use asio::async_resolve like this:

async_resolve("127.0.0.1", "daytime")
  .then([](udp::resolver::iterator iterator) {
    // ...
  });

asio and boost::asio async completion tokens

Since version 4.0.0 continuable also supports asio async initiation tokens.

  • Boost 1.70 or asio 1.13.0 is required for the async initiation
  • Until boost 1.72 or asio 1.16.0 overhead through an additional type erasure is added. It is recommended to update to those versions.

The special static variable cti::use_continuable can be appended to any (boost) asio function that accepts a callback to make it return a continuable_base.

#include <continuable/continuable.hpp>
#include <continuable/external/asio.hpp>
#include <asio.hpp>

// ...

asio::tcp::resolver resolver(...);
resolver.async_resolve("127.0.0.1", "daytime", cti::use_continuable)
  .then([](asio::udp::resolver::iterator iterator) {
    // ...
  });