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:
handler_type
. Ce modèle est utilisé pour déterminer le gestionnaire à utiliser en fonction de la signature de l’opération asynchrone. 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