boost :: asio avec boost :: unique_future

Selon http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/cpp2011/futures.html , nous pouvons utiliser boost :: asio avec std::future . Mais je n’ai trouvé aucune information sur l’utilisation de boost::unique_future , qui comporte davantage de fonctions, telles que then() . Comment puis-je utiliser?

Boost.Asio fournit uniquement un support de première classe pour les opérations asynchrones permettant de renvoyer un C ++ 11 std::future ou une valeur réelle dans des coroutines empilées . Néanmoins, la configuration requirejse pour les opérations asynchrones explique comment personnaliser le type de retour pour d’autres types, tels que boost::unique_future . Cela requirejs:

  • Une spécialisation du modèle handler_type . Ce modèle est utilisé pour déterminer le gestionnaire à utiliser en fonction de la signature de l’opération asynchrone.
  • Une spécialisation du modèle async_result . Ce modèle est utilisé à la fois pour déterminer le type de retour et pour extraire la valeur de retour du gestionnaire.

Vous trouverez ci-dessous un exemple complet minimal illustrant la deadline_timer::async_wait() boost:unique_future avec un calcul de base exécuté sur une série de suites composées avec .then() . Pour que l’exemple rest simple, j’ai choisi de spécialiser uniquement handler_type pour les signatures d’opération asynchrone utilisées dans l’exemple. Pour une référence complète, je suggère vivement de passer en revue use_future.hpp et impl/use_future.hpp .

 #include  // current_exception, make_exception_ptr #include  // make_shared, shared_ptr #include  // thread #include  // move #define BOOST_RESULT_OF_USE_DECLTYPE #define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION #include  #include  #include  /// @brief Class used to indicate an asynchronous operation should return /// a boost::unique_future. class use_unique_future_t {}; /// @brief A special value, similiar to std::nothrow. constexpr use_unique_future_t use_unique_future; namespace detail { /// @brief Completion handler to adapt a boost::promise as a completion /// handler. template  class unique_promise_handler; /// @brief Completion handler to adapt a void boost::promise as a completion /// handler. template <> class unique_promise_handler { public: /// @brief Construct from use_unique_future special value. explicit unique_promise_handler(use_unique_future_t) : promise_(std::make_shared >()) {} void operator()(const boost::system::error_code& error) { // On error, convert the error code into an exception and set it on // the promise. if (error) promise_->set_exception( std::make_exception_ptr(boost::system::system_error(error))); // Otherwise, set the value. else promise_->set_value(); } //private: std::shared_ptr > promise_; }; // Ensure any exceptions thrown from the handler are propagated back to the // caller via the future. template  void asio_handler_invoke( Function function, unique_promise_handler* handler) { // Guarantee the promise lives for the duration of the function call. std::shared_ptr > promise(handler->promise_); try { function(); } catch (...) { promise->set_exception(std::current_exception()); } } } // namespace detail namespace boost { namespace asio { /// @brief Handler type specialization for use_unique_future. template  struct handler_type< use_unique_future_t, ReturnType(boost::system::error_code)> { typedef ::detail::unique_promise_handler type; }; /// @brief Handler traits specialization for unique_promise_handler. template  class async_result< ::detail::unique_promise_handler > { public: // The initiating function will return a boost::unique_future. typedef boost::unique_future type; // Constructor creates a new promise for the async operation, and obtains the // corresponding future. explicit async_result(::detail::unique_promise_handler& handler) { value_ = handler.promise_->get_future(); } // Obtain the future to be returned from the initiating function. type get() { return std::move(value_); } private: type value_; }; } // namespace asio } // namespace boost int main() { boost::asio::io_service io_service; boost::asio::io_service::work work(io_service); // Run io_service in its own thread to demonstrate future usage. std::thread thread([&io_service](){ io_service.run(); }); // Arm 3 second timer. boost::asio::deadline_timer timer( io_service, boost::posix_time::seconds(3)); // Asynchronously wait on the timer, then perform basic calculations // within the future's continuations. boost::unique_future result = timer.async_wait(use_unique_future) .then([](boost::unique_future future){ std::cout << "calculation 1" << std::endl; return 21; }) .then([](boost::unique_future future){ std::cout << "calculation 2" << std::endl; return 2 * future.get(); }) ; std::cout << "Waiting for result" << std::endl; // Wait for the timer to trigger and for its continuations to calculate // the result. std::cout << result.get() << std::endl; // Cleanup. io_service.stop(); thread.join(); } 

Sortie:

 Waiting for result calculation 1 calculation 2 42