| // |
| // package.hpp |
| // ~~~~~~~~~~~ |
| // |
| // Copyright (c) 2003-2015 Christopher M. Kohlhoff (chris at kohlhoff dot com) |
| // |
| // Distributed under the Boost Software License, Version 1.0. (See accompanying |
| // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) |
| // |
| |
| #ifndef ASIO_USE_PACKAGE_HPP |
| #define ASIO_USE_PACKAGE_HPP |
| |
| #if defined(_MSC_VER) && (_MSC_VER >= 1200) |
| # pragma once |
| #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) |
| |
| #include "asio/detail/config.hpp" |
| #include <future> |
| #include <memory> |
| #include "asio/async_result.hpp" |
| #include "asio/detail/type_traits.hpp" |
| #include "asio/detail/variadic_templates.hpp" |
| #include "asio/handler_type.hpp" |
| |
| #include "asio/detail/push_options.hpp" |
| |
| namespace asio { |
| |
| /// Class to enable lazy construction of a packaged_task from a completion |
| /// token. |
| /** |
| * The packaged_token class is used to adapt a function object as a packaged |
| * task. When this adapter is passed as a completion token to an asynchronous |
| * operation, the result of the function object is retuned via a std::future. |
| * |
| * Use the @ref package function rather than using this class directly. |
| */ |
| template <typename Function, typename Allocator = std::allocator<void> > |
| class packaged_token |
| { |
| public: |
| /// The allocator type. The allocator is used when constructing the |
| /// @c std::promise object for a given asynchronous operation. |
| typedef Allocator allocator_type; |
| |
| /// Construct using specified allocator. |
| explicit packaged_token(Function f) |
| : func_(std::move(f)) |
| { |
| } |
| |
| /// Construct using specified allocator. |
| packaged_token(Function f, const Allocator& allocator) |
| : func_(std::move(f)), |
| allocator_(allocator) |
| { |
| } |
| |
| /// Obtain allocator. |
| allocator_type get_allocator() const ASIO_NOEXCEPT |
| { |
| return allocator_; |
| } |
| |
| private: |
| template <class, class> friend class packaged_handler; |
| Function func_; |
| Allocator allocator_; |
| }; |
| |
| /// A packaged_task with an associated allocator. |
| template <typename Signature, typename Allocator> |
| class packaged_handler : public std::packaged_task<Signature> |
| { |
| public: |
| /// The allocator type. The allocator is used when constructing the |
| /// @c std::promise object for a given asynchronous operation. |
| typedef Allocator allocator_type; |
| |
| /// Construct from a packaged token. |
| template <typename Function> |
| packaged_handler( |
| packaged_token<Function, Allocator>&& token) |
| #if defined(_MSC_VER) |
| : std::packaged_task<Signature>(std::move(token.func_)), |
| #elif defined(ASIO_HAS_CLANG_LIBCXX) |
| : std::packaged_task<Signature>(std::allocator_arg, |
| typename std::allocator_traits< |
| Allocator>::template rebind_alloc<char>(token.allocator_), |
| std::move(token.func_)), |
| #else |
| : std::packaged_task<Signature>(std::allocator_arg, |
| token.allocator_, std::move(token.func_)), |
| #endif |
| allocator_(token.allocator_) |
| { |
| } |
| |
| /// Move construct from another packaged handler. |
| packaged_handler(packaged_handler&& other) |
| : std::packaged_task<Signature>( |
| static_cast<std::packaged_task<Signature>&&>(other)), |
| allocator_(other.allocator_) |
| { |
| } |
| |
| /// Obtain allocator. |
| allocator_type get_allocator() const ASIO_NOEXCEPT |
| { |
| return allocator_; |
| } |
| |
| private: |
| Allocator allocator_; |
| }; |
| |
| /// Wrap a function object in a packaged task. |
| /** |
| * The @c package function is used to adapt a function object as a packaged |
| * task. When this adapter is passed as a completion token to an asynchronous |
| * operation, the result of the function object is retuned via a std::future. |
| * |
| * @par Example |
| * |
| * @code std::future<std::size_t> fut = |
| * my_socket.async_read_some(buffer, |
| * package([](asio::error_code ec, std::size_t n) |
| * { |
| * return ec ? 0 : n; |
| * })); |
| * ... |
| * std::size_t n = fut.get(); @endcode |
| */ |
| template <typename Function> |
| inline packaged_token<typename decay<Function>::type, std::allocator<void> > |
| package(ASIO_MOVE_ARG(Function) function) |
| { |
| return packaged_token<typename decay<Function>::type, std::allocator<void> >( |
| ASIO_MOVE_CAST(Function)(function), std::allocator<void>()); |
| } |
| |
| /// Wrap a function object in a packaged task. |
| /** |
| * The @c package function is used to adapt a function object as a packaged |
| * task. When this adapter is passed as a completion token to an asynchronous |
| * operation, the result of the function object is retuned via a std::future. |
| * |
| * @par Example |
| * |
| * @code std::future<std::size_t> fut = |
| * my_socket.async_read_some(buffer, |
| * package([](asio::error_code ec, std::size_t n) |
| * { |
| * return ec ? 0 : n; |
| * })); |
| * ... |
| * std::size_t n = fut.get(); @endcode |
| */ |
| template <typename Function, typename Allocator> |
| inline packaged_token<typename decay<Function>::type, Allocator> package( |
| ASIO_MOVE_ARG(Function) function, const Allocator& a) |
| { |
| return packaged_token<typename decay<Function>::type, Allocator>( |
| ASIO_MOVE_CAST(Function)(function), a); |
| } |
| |
| #if !defined(GENERATING_DOCUMENTATION) |
| |
| #if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
| |
| template <typename Function, typename Allocator, typename R, typename... Args> |
| struct handler_type<packaged_token<Function, Allocator>, R(Args...)> |
| { |
| typedef packaged_handler< |
| typename result_of<Function(Args...)>::type(Args...), |
| Allocator> type; |
| }; |
| |
| #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
| |
| template <typename Function, typename Allocator, typename R> |
| struct handler_type<packaged_token<Function, Allocator>, R()> |
| { |
| typedef packaged_handler< |
| typename result_of<Function()>::type(), |
| Allocator> type; |
| }; |
| |
| #define ASIO_PRIVATE_HANDLER_TYPE_DEF(n) \ |
| template <typename Function, typename Allocator, \ |
| typename R, ASIO_VARIADIC_TPARAMS(n)> \ |
| struct handler_type< \ |
| packaged_token<Function, Allocator>, R(ASIO_VARIADIC_TARGS(n))> \ |
| { \ |
| typedef packaged_handler< \ |
| typename result_of< \ |
| Function(ASIO_VARIADIC_TARGS(n))>::type( \ |
| ASIO_VARIADIC_TARGS(n)), \ |
| Allocator> type; \ |
| }; \ |
| /**/ |
| ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_TYPE_DEF) |
| #undef ASIO_PRIVATE_HANDLER_TYPE_DEF |
| |
| #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
| |
| #if defined(ASIO_HAS_VARIADIC_TEMPLATES) |
| |
| template <typename R, typename... Args> |
| class async_result<std::packaged_task<R(Args...)> > |
| { |
| public: |
| typedef std::future<R> type; |
| |
| explicit async_result(std::packaged_task<R(Args...)>& h) |
| : future_(h.get_future()) |
| { |
| } |
| |
| type get() |
| { |
| return std::move(future_); |
| } |
| |
| private: |
| type future_; |
| }; |
| |
| #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
| |
| template <typename R> |
| class async_result<std::packaged_task<R()> > |
| { |
| public: |
| typedef std::future<R> type; |
| |
| explicit async_result(std::packaged_task<R()>& h) |
| : future_(h.get_future()) |
| { |
| } |
| |
| type get() |
| { |
| return std::move(future_); |
| } |
| |
| private: |
| type future_; |
| }; |
| |
| #define ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \ |
| template <typename R, ASIO_VARIADIC_TPARAMS(n)> \ |
| class async_result<std::packaged_task<R(ASIO_VARIADIC_TARGS(n))> > \ |
| { \ |
| public: \ |
| typedef std::future<R> type; \ |
| \ |
| explicit async_result( \ |
| std::packaged_task<R(ASIO_VARIADIC_TARGS(n))>& h) \ |
| : future_(h.get_future()) \ |
| { \ |
| } \ |
| \ |
| type get() \ |
| { \ |
| return std::move(future_); \ |
| } \ |
| \ |
| private: \ |
| type future_; \ |
| }; \ |
| /**/ |
| ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF) |
| #undef ASIO_PRIVATE_ASYNC_RESULT_DEF |
| |
| #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) |
| |
| template <typename Signature, typename Allocator> |
| class async_result<packaged_handler<Signature, Allocator>> |
| : public async_result<std::packaged_task<Signature>> |
| { |
| public: |
| explicit async_result(packaged_handler<Signature, Allocator>& h) |
| : async_result<std::packaged_task<Signature>>(h) {} |
| }; |
| |
| #endif // !defined(GENERATING_DOCUMENTATION) |
| |
| } // namespace asio |
| |
| #include "asio/detail/pop_options.hpp" |
| |
| #endif // ASIO_USE_PACKAGE_HPP |