boost::asio mit boost::unique_future

Lesezeit: 4 Minuten

Entsprechend http://www.boost.org/doc/libs/1_55_0/doc/html/boost_asio/overview/cpp2011/futures.htmlkönnen wir boost::asio mit verwenden std::future. Aber ich konnte keine Informationen über die Arbeit mit finden boost::unique_futuredie mehr Funktionen hat, wie z then(). Wie kann ich verwenden?

Boost.Asio bietet nur erstklassige Unterstützung für asynchrone Operationen, um ein C++11 zurückzugeben std::future oder ein tatsächlicher Wert in Stapelbare Coroutinen. Trotzdem ist die Anforderungen an asynchrone Operationen dokumentiert, wie der Rückgabetyp für andere Typen, wie z. B. Boost.Thread, angepasst werden kann boost::unique_future. Es benötigt:

  • Eine Spezialisierung der handler_type Schablone. Diese Vorlage wird verwendet, um den tatsächlich zu verwendenden Handler basierend auf der Signatur des asynchronen Vorgangs zu bestimmen.
  • Eine Spezialisierung der async_result Schablone. Diese Vorlage wird sowohl zur Bestimmung des Rückgabetyps als auch zur Extraktion des Rückgabewerts aus dem Handler verwendet.

Unten ist ein minimales vollständiges Beispiel, das demonstriert deadline_timer::async_wait() Rückkehr boost:unique_future wobei eine grundlegende Berechnung über eine Reihe von Fortsetzungen durchgeführt wird, die mit zusammengesetzt sind .then(). Um das Beispiel einfach zu halten, habe ich mich dafür entschieden, mich nur zu spezialisieren handler_type für die im Beispiel verwendeten asynchronen Vorgangssignaturen. Für eine vollständige Referenz empfehle ich dringend eine Überprüfung use_future.hpp und impl/use_future.hpp.

#include <exception> // current_exception, make_exception_ptr
#include <memory> // make_shared, shared_ptr
#include <thread> // thread
#include <utility> // move

#define BOOST_RESULT_OF_USE_DECLTYPE
#define BOOST_THREAD_PROVIDES_FUTURE_CONTINUATION

#include <boost/asio.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
#include <boost/thread/future.hpp>

/// @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 <typename T>
class unique_promise_handler;

/// @brief Completion handler to adapt a void boost::promise as a completion
///        handler.
template <>
class unique_promise_handler<void>
{
public:
  /// @brief Construct from use_unique_future special value.
  explicit unique_promise_handler(use_unique_future_t)
    : promise_(std::make_shared<boost::promise<void> >())
  {}

  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<boost::promise<void> > promise_;
};

// Ensure any exceptions thrown from the handler are propagated back to the
// caller via the future.
template <typename Function, typename T>
void asio_handler_invoke(
    Function function,
    unique_promise_handler<T>* handler)
{
  // Guarantee the promise lives for the duration of the function call.
  std::shared_ptr<boost::promise<T> > 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 <typename ReturnType>
struct handler_type<
    use_unique_future_t,
    ReturnType(boost::system::error_code)>
{
  typedef ::detail::unique_promise_handler<void> type;
};

/// @brief Handler traits specialization for unique_promise_handler.
template <typename T>
class async_result< ::detail::unique_promise_handler<T> >
{
public:
  // The initiating function will return a boost::unique_future.
  typedef boost::unique_future<T> type;

  // Constructor creates a new promise for the async operation, and obtains the
  // corresponding future.
  explicit async_result(::detail::unique_promise_handler<T>& 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<int> result =
      timer.async_wait(use_unique_future)
        .then([](boost::unique_future<void> future){
           std::cout << "calculation 1" << std::endl;
           return 21;
        })
        .then([](boost::unique_future<int> 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();
}

Ausgabe:

Waiting for result
calculation 1
calculation 2
42

1012790cookie-checkboost::asio mit boost::unique_future

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy