Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:33:43

0001 //
0002 // compose.hpp
0003 // ~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)
0006 //
0007 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0008 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0009 //
0010 
0011 #ifndef BOOST_ASIO_COMPOSE_HPP
0012 #define BOOST_ASIO_COMPOSE_HPP
0013 
0014 #if defined(_MSC_VER) && (_MSC_VER >= 1200)
0015 # pragma once
0016 #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
0017 
0018 #include <boost/asio/detail/config.hpp>
0019 #include <boost/asio/associated_executor.hpp>
0020 #include <boost/asio/async_result.hpp>
0021 #include <boost/asio/detail/base_from_cancellation_state.hpp>
0022 #include <boost/asio/detail/composed_work.hpp>
0023 #include <boost/asio/detail/handler_cont_helpers.hpp>
0024 #include <boost/asio/detail/type_traits.hpp>
0025 
0026 #include <boost/asio/detail/push_options.hpp>
0027 
0028 namespace boost {
0029 namespace asio {
0030 namespace detail {
0031 
0032 template <typename Impl, typename Work, typename Handler, typename Signature>
0033 class composed_op;
0034 
0035 template <typename Impl, typename Work, typename Handler,
0036     typename R, typename... Args>
0037 class composed_op<Impl, Work, Handler, R(Args...)>
0038   : public base_from_cancellation_state<Handler>
0039 {
0040 public:
0041   template <typename I, typename W, typename H>
0042   composed_op(I&& impl,
0043       W&& work,
0044       H&& handler)
0045     : base_from_cancellation_state<Handler>(
0046         handler, enable_terminal_cancellation()),
0047       impl_(static_cast<I&&>(impl)),
0048       work_(static_cast<W&&>(work)),
0049       handler_(static_cast<H&&>(handler)),
0050       invocations_(0)
0051   {
0052   }
0053 
0054   composed_op(composed_op&& other)
0055     : base_from_cancellation_state<Handler>(
0056         static_cast<base_from_cancellation_state<Handler>&&>(other)),
0057       impl_(static_cast<Impl&&>(other.impl_)),
0058       work_(static_cast<Work&&>(other.work_)),
0059       handler_(static_cast<Handler&&>(other.handler_)),
0060       invocations_(other.invocations_)
0061   {
0062   }
0063 
0064   typedef typename composed_work_guard<
0065     typename Work::head_type>::executor_type io_executor_type;
0066 
0067   io_executor_type get_io_executor() const noexcept
0068   {
0069     return work_.head_.get_executor();
0070   }
0071 
0072   typedef associated_executor_t<Handler, io_executor_type> executor_type;
0073 
0074   executor_type get_executor() const noexcept
0075   {
0076     return (get_associated_executor)(handler_, work_.head_.get_executor());
0077   }
0078 
0079   typedef associated_allocator_t<Handler, std::allocator<void>> allocator_type;
0080 
0081   allocator_type get_allocator() const noexcept
0082   {
0083     return (get_associated_allocator)(handler_, std::allocator<void>());
0084   }
0085 
0086   template<typename... T>
0087   void operator()(T&&... t)
0088   {
0089     if (invocations_ < ~0u)
0090       ++invocations_;
0091     this->get_cancellation_state().slot().clear();
0092     impl_(*this, static_cast<T&&>(t)...);
0093   }
0094 
0095   void complete(Args... args)
0096   {
0097     this->work_.reset();
0098     static_cast<Handler&&>(this->handler_)(static_cast<Args&&>(args)...);
0099   }
0100 
0101   void reset_cancellation_state()
0102   {
0103     base_from_cancellation_state<Handler>::reset_cancellation_state(handler_);
0104   }
0105 
0106   template <typename Filter>
0107   void reset_cancellation_state(Filter&& filter)
0108   {
0109     base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
0110         static_cast<Filter&&>(filter));
0111   }
0112 
0113   template <typename InFilter, typename OutFilter>
0114   void reset_cancellation_state(InFilter&& in_filter,
0115       OutFilter&& out_filter)
0116   {
0117     base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
0118         static_cast<InFilter&&>(in_filter),
0119         static_cast<OutFilter&&>(out_filter));
0120   }
0121 
0122   cancellation_type_t cancelled() const noexcept
0123   {
0124     return base_from_cancellation_state<Handler>::cancelled();
0125   }
0126 
0127 //private:
0128   Impl impl_;
0129   Work work_;
0130   Handler handler_;
0131   unsigned invocations_;
0132 };
0133 
0134 template <typename Impl, typename Work, typename Handler, typename Signature>
0135 inline bool asio_handler_is_continuation(
0136     composed_op<Impl, Work, Handler, Signature>* this_handler)
0137 {
0138   return this_handler->invocations_ > 1 ? true
0139     : boost_asio_handler_cont_helpers::is_continuation(
0140         this_handler->handler_);
0141 }
0142 
0143 template <typename Signature, typename Executors>
0144 class initiate_composed_op
0145 {
0146 public:
0147   typedef typename composed_io_executors<Executors>::head_type executor_type;
0148 
0149   template <typename T>
0150   explicit initiate_composed_op(int, T&& executors)
0151     : executors_(static_cast<T&&>(executors))
0152   {
0153   }
0154 
0155   executor_type get_executor() const noexcept
0156   {
0157     return executors_.head_;
0158   }
0159 
0160   template <typename Handler, typename Impl>
0161   void operator()(Handler&& handler,
0162       Impl&& impl) const
0163   {
0164     composed_op<decay_t<Impl>, composed_work<Executors>,
0165       decay_t<Handler>, Signature>(
0166         static_cast<Impl&&>(impl),
0167         composed_work<Executors>(executors_),
0168         static_cast<Handler&&>(handler))();
0169   }
0170 
0171 private:
0172   composed_io_executors<Executors> executors_;
0173 };
0174 
0175 template <typename Signature, typename Executors>
0176 inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(
0177     composed_io_executors<Executors>&& executors)
0178 {
0179   return initiate_composed_op<Signature, Executors>(0,
0180       static_cast<composed_io_executors<Executors>&&>(executors));
0181 }
0182 
0183 } // namespace detail
0184 
0185 #if !defined(GENERATING_DOCUMENTATION)
0186 
0187 template <template <typename, typename> class Associator,
0188     typename Impl, typename Work, typename Handler,
0189     typename Signature, typename DefaultCandidate>
0190 struct associator<Associator,
0191     detail::composed_op<Impl, Work, Handler, Signature>,
0192     DefaultCandidate>
0193   : Associator<Handler, DefaultCandidate>
0194 {
0195   static typename Associator<Handler, DefaultCandidate>::type get(
0196       const detail::composed_op<Impl, Work, Handler, Signature>& h) noexcept
0197   {
0198     return Associator<Handler, DefaultCandidate>::get(h.handler_);
0199   }
0200 
0201   static auto get(const detail::composed_op<Impl, Work, Handler, Signature>& h,
0202       const DefaultCandidate& c) noexcept
0203     -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c))
0204   {
0205     return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
0206   }
0207 };
0208 
0209 #endif // !defined(GENERATING_DOCUMENTATION)
0210 
0211 /// Launch an asynchronous operation with a stateful implementation.
0212 /**
0213  * The async_compose function simplifies the implementation of composed
0214  * asynchronous operations automatically wrapping a stateful function object
0215  * with a conforming intermediate completion handler.
0216  *
0217  * @param implementation A function object that contains the implementation of
0218  * the composed asynchronous operation. The first argument to the function
0219  * object is a non-const reference to the enclosing intermediate completion
0220  * handler. The remaining arguments are any arguments that originate from the
0221  * completion handlers of any asynchronous operations performed by the
0222  * implementation.
0223  *
0224  * @param token The completion token.
0225  *
0226  * @param io_objects_or_executors Zero or more I/O objects or I/O executors for
0227  * which outstanding work must be maintained.
0228  *
0229  * @par Per-Operation Cancellation
0230  * By default, terminal per-operation cancellation is enabled for
0231  * composed operations that are implemented using @c async_compose. To
0232  * disable cancellation for the composed operation, or to alter its
0233  * supported cancellation types, call the @c self object's @c
0234  * reset_cancellation_state function.
0235  *
0236  * @par Example:
0237  *
0238  * @code struct async_echo_implementation
0239  * {
0240  *   tcp::socket& socket_;
0241  *   boost::asio::mutable_buffer buffer_;
0242  *   enum { starting, reading, writing } state_;
0243  *
0244  *   template <typename Self>
0245  *   void operator()(Self& self,
0246  *       boost::system::error_code error = {},
0247  *       std::size_t n = 0)
0248  *   {
0249  *     switch (state_)
0250  *     {
0251  *     case starting:
0252  *       state_ = reading;
0253  *       socket_.async_read_some(
0254  *           buffer_, std::move(self));
0255  *       break;
0256  *     case reading:
0257  *       if (error)
0258  *       {
0259  *         self.complete(error, 0);
0260  *       }
0261  *       else
0262  *       {
0263  *         state_ = writing;
0264  *         boost::asio::async_write(socket_, buffer_,
0265  *             boost::asio::transfer_exactly(n),
0266  *             std::move(self));
0267  *       }
0268  *       break;
0269  *     case writing:
0270  *       self.complete(error, n);
0271  *       break;
0272  *     }
0273  *   }
0274  * };
0275  *
0276  * template <typename CompletionToken>
0277  * auto async_echo(tcp::socket& socket,
0278  *     boost::asio::mutable_buffer buffer,
0279  *     CompletionToken&& token) ->
0280  *   decltype(
0281  *     boost::asio::async_compose<CompletionToken,
0282  *       void(boost::system::error_code, std::size_t)>(
0283  *         std::declval<async_echo_implementation>(),
0284  *         token, socket))
0285  * {
0286  *   return boost::asio::async_compose<CompletionToken,
0287  *     void(boost::system::error_code, std::size_t)>(
0288  *       async_echo_implementation{socket, buffer,
0289  *         async_echo_implementation::starting},
0290  *       token, socket);
0291  * } @endcode
0292  */
0293 template <typename CompletionToken, typename Signature,
0294     typename Implementation, typename... IoObjectsOrExecutors>
0295 auto async_compose(Implementation&& implementation,
0296     type_identity_t<CompletionToken>& token,
0297     IoObjectsOrExecutors&&... io_objects_or_executors)
0298   -> decltype(
0299     async_initiate<CompletionToken, Signature>(
0300       detail::make_initiate_composed_op<Signature>(
0301         detail::make_composed_io_executors(
0302           detail::get_composed_io_executor(
0303             static_cast<IoObjectsOrExecutors&&>(
0304               io_objects_or_executors))...)),
0305       token, static_cast<Implementation&&>(implementation)))
0306 {
0307   return async_initiate<CompletionToken, Signature>(
0308       detail::make_initiate_composed_op<Signature>(
0309         detail::make_composed_io_executors(
0310           detail::get_composed_io_executor(
0311             static_cast<IoObjectsOrExecutors&&>(
0312               io_objects_or_executors))...)),
0313       token, static_cast<Implementation&&>(implementation));
0314 }
0315 
0316 } // namespace asio
0317 } // namespace boost
0318 
0319 #include <boost/asio/detail/pop_options.hpp>
0320 
0321 #endif // BOOST_ASIO_COMPOSE_HPP