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_future
die mehr Funktionen hat, wie z then()
. Wie kann ich verwenden?
boost::asio mit boost::unique_future
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