Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-04-26 08:25:30

0001 //
0002 // composed.hpp
0003 // ~~~~~~~~~~~~
0004 //
0005 // Copyright (c) 2003-2024 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_COMPOSED_HPP
0012 #define BOOST_ASIO_COMPOSED_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,
0033     typename Handler, typename... Signatures>
0034 class composed_op;
0035 
0036 template <typename Impl, typename Work, typename Handler>
0037 class composed_op<Impl, Work, Handler>
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   template <typename... Args>
0096   auto complete(Args&&... args)
0097     -> decltype(declval<Handler>()(static_cast<Args&&>(args)...))
0098   {
0099     return static_cast<Handler&&>(this->handler_)(static_cast<Args&&>(args)...);
0100   }
0101 
0102   void reset_cancellation_state()
0103   {
0104     base_from_cancellation_state<Handler>::reset_cancellation_state(handler_);
0105   }
0106 
0107   template <typename Filter>
0108   void reset_cancellation_state(Filter&& filter)
0109   {
0110     base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
0111         static_cast<Filter&&>(filter));
0112   }
0113 
0114   template <typename InFilter, typename OutFilter>
0115   void reset_cancellation_state(InFilter&& in_filter,
0116       OutFilter&& out_filter)
0117   {
0118     base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,
0119         static_cast<InFilter&&>(in_filter),
0120         static_cast<OutFilter&&>(out_filter));
0121   }
0122 
0123   cancellation_type_t cancelled() const noexcept
0124   {
0125     return base_from_cancellation_state<Handler>::cancelled();
0126   }
0127 
0128 //private:
0129   Impl impl_;
0130   Work work_;
0131   Handler handler_;
0132   unsigned invocations_;
0133 };
0134 
0135 template <typename Impl, typename Work, typename Handler,
0136     typename R, typename... Args>
0137 class composed_op<Impl, Work, Handler, R(Args...)>
0138   : public composed_op<Impl, Work, Handler>
0139 {
0140 public:
0141   using composed_op<Impl, Work, Handler>::composed_op;
0142 
0143   template <typename... T>
0144   void operator()(T&&... t)
0145   {
0146     if (this->invocations_ < ~0u)
0147       ++this->invocations_;
0148     this->get_cancellation_state().slot().clear();
0149     this->impl_(*this, static_cast<T&&>(t)...);
0150   }
0151 
0152   void complete(Args... args)
0153   {
0154     this->work_.reset();
0155     static_cast<Handler&&>(this->handler_)(static_cast<Args&&>(args)...);
0156   }
0157 };
0158 
0159 template <typename Impl, typename Work, typename Handler,
0160     typename R, typename... Args, typename... Signatures>
0161 class composed_op<Impl, Work, Handler, R(Args...), Signatures...>
0162   : public composed_op<Impl, Work, Handler, Signatures...>
0163 {
0164 public:
0165   using composed_op<Impl, Work, Handler, Signatures...>::composed_op;
0166 
0167   template <typename... T>
0168   void operator()(T&&... t)
0169   {
0170     if (this->invocations_ < ~0u)
0171       ++this->invocations_;
0172     this->get_cancellation_state().slot().clear();
0173     this->impl_(*this, static_cast<T&&>(t)...);
0174   }
0175 
0176   using composed_op<Impl, Work, Handler, Signatures...>::complete;
0177 
0178   void complete(Args... args)
0179   {
0180     this->work_.reset();
0181     static_cast<Handler&&>(this->handler_)(static_cast<Args&&>(args)...);
0182   }
0183 };
0184 
0185 template <typename Impl, typename Work, typename Handler, typename Signature>
0186 inline bool asio_handler_is_continuation(
0187     composed_op<Impl, Work, Handler, Signature>* this_handler)
0188 {
0189   return this_handler->invocations_ > 1 ? true
0190     : boost_asio_handler_cont_helpers::is_continuation(
0191         this_handler->handler_);
0192 }
0193 
0194 template <typename Implementation, typename Executors, typename... Signatures>
0195 class initiate_composed
0196 {
0197 public:
0198   typedef typename composed_io_executors<Executors>::head_type executor_type;
0199 
0200   template <typename I>
0201   initiate_composed(I&& impl, composed_io_executors<Executors>&& executors)
0202     : implementation_(std::forward<I>(impl)),
0203       executors_(std::move(executors))
0204   {
0205   }
0206 
0207   executor_type get_executor() const noexcept
0208   {
0209     return executors_.head_;
0210   }
0211 
0212   template <typename Handler, typename... Args>
0213   void operator()(Handler&& handler, Args&&... args) const &
0214   {
0215     composed_op<decay_t<Implementation>, composed_work<Executors>,
0216       decay_t<Handler>, Signatures...>(implementation_,
0217         composed_work<Executors>(executors_),
0218         static_cast<Handler&&>(handler))(static_cast<Args&&>(args)...);
0219   }
0220 
0221   template <typename Handler, typename... Args>
0222   void operator()(Handler&& handler, Args&&... args) &&
0223   {
0224     composed_op<decay_t<Implementation>, composed_work<Executors>,
0225       decay_t<Handler>, Signatures...>(
0226         static_cast<Implementation&&>(implementation_),
0227         composed_work<Executors>(executors_),
0228         static_cast<Handler&&>(handler))(static_cast<Args&&>(args)...);
0229   }
0230 
0231 private:
0232   Implementation implementation_;
0233   composed_io_executors<Executors> executors_;
0234 };
0235 
0236 template <typename Implementation, typename... Signatures>
0237 class initiate_composed<Implementation, void(), Signatures...>
0238 {
0239 public:
0240   template <typename I>
0241   initiate_composed(I&& impl, composed_io_executors<void()>&&)
0242     : implementation_(std::forward<I>(impl))
0243   {
0244   }
0245 
0246   template <typename Handler, typename... Args>
0247   void operator()(Handler&& handler, Args&&... args) const &
0248   {
0249     composed_op<decay_t<Implementation>, composed_work<void()>,
0250       decay_t<Handler>, Signatures...>(implementation_,
0251         composed_work<void()>(composed_io_executors<void()>()),
0252         static_cast<Handler&&>(handler))(static_cast<Args&&>(args)...);
0253   }
0254 
0255   template <typename Handler, typename... Args>
0256   void operator()(Handler&& handler, Args&&... args) &&
0257   {
0258     composed_op<decay_t<Implementation>, composed_work<void()>,
0259       decay_t<Handler>, Signatures...>(
0260         static_cast<Implementation&&>(implementation_),
0261         composed_work<void()>(composed_io_executors<void()>()),
0262         static_cast<Handler&&>(handler))(static_cast<Args&&>(args)...);
0263   }
0264 
0265 private:
0266   Implementation implementation_;
0267 };
0268 
0269 template <typename... Signatures, typename Implementation, typename Executors>
0270 inline initiate_composed<Implementation, Executors, Signatures...>
0271 make_initiate_composed(Implementation&& implementation,
0272     composed_io_executors<Executors>&& executors)
0273 {
0274   return initiate_composed<decay_t<Implementation>, Executors, Signatures...>(
0275       static_cast<Implementation&&>(implementation),
0276       static_cast<composed_io_executors<Executors>&&>(executors));
0277 }
0278 
0279 } // namespace detail
0280 
0281 #if !defined(GENERATING_DOCUMENTATION)
0282 
0283 template <template <typename, typename> class Associator,
0284     typename Impl, typename Work, typename Handler,
0285     typename Signature, typename DefaultCandidate>
0286 struct associator<Associator,
0287     detail::composed_op<Impl, Work, Handler, Signature>,
0288     DefaultCandidate>
0289   : Associator<Handler, DefaultCandidate>
0290 {
0291   static typename Associator<Handler, DefaultCandidate>::type get(
0292       const detail::composed_op<Impl, Work, Handler, Signature>& h) noexcept
0293   {
0294     return Associator<Handler, DefaultCandidate>::get(h.handler_);
0295   }
0296 
0297   static auto get(const detail::composed_op<Impl, Work, Handler, Signature>& h,
0298       const DefaultCandidate& c) noexcept
0299     -> decltype(Associator<Handler, DefaultCandidate>::get(h.handler_, c))
0300   {
0301     return Associator<Handler, DefaultCandidate>::get(h.handler_, c);
0302   }
0303 };
0304 
0305 #endif // !defined(GENERATING_DOCUMENTATION)
0306 
0307 /// Creates an initiation function object that may be used to launch an
0308 /// asynchronous operation with a stateful implementation.
0309 /**
0310  * The @c composed function simplifies the implementation of composed
0311  * asynchronous operations automatically by wrapping a stateful function object
0312  * for use as an initiation function object.
0313  *
0314  * @param implementation A function object that contains the implementation of
0315  * the composed asynchronous operation. The first argument to the function
0316  * object is a non-const reference to the enclosing intermediate completion
0317  * handler. The remaining arguments are any arguments that originate from the
0318  * completion handlers of any asynchronous operations performed by the
0319  * implementation.
0320  *
0321  * @param io_objects_or_executors Zero or more I/O objects or I/O executors for
0322  * which outstanding work must be maintained.
0323  *
0324  * @par Per-Operation Cancellation
0325  * By default, terminal per-operation cancellation is enabled for composed
0326  * operations that are implemented using @c composed. To disable cancellation
0327  * for the composed operation, or to alter its supported cancellation types,
0328  * call the @c self object's @c reset_cancellation_state function.
0329  *
0330  * @par Example:
0331  *
0332  * @code struct async_echo_implementation
0333  * {
0334  *   tcp::socket& socket_;
0335  *   boost::asio::mutable_buffer buffer_;
0336  *   enum { starting, reading, writing } state_;
0337  *
0338  *   template <typename Self>
0339  *   void operator()(Self& self,
0340  *       boost::system::error_code error,
0341  *       std::size_t n)
0342  *   {
0343  *     switch (state_)
0344  *     {
0345  *     case starting:
0346  *       state_ = reading;
0347  *       socket_.async_read_some(
0348  *           buffer_, std::move(self));
0349  *       break;
0350  *     case reading:
0351  *       if (error)
0352  *       {
0353  *         self.complete(error, 0);
0354  *       }
0355  *       else
0356  *       {
0357  *         state_ = writing;
0358  *         boost::asio::async_write(socket_, buffer_,
0359  *             boost::asio::transfer_exactly(n),
0360  *             std::move(self));
0361  *       }
0362  *       break;
0363  *     case writing:
0364  *       self.complete(error, n);
0365  *       break;
0366  *     }
0367  *   }
0368  * };
0369  *
0370  * template <typename CompletionToken>
0371  * auto async_echo(tcp::socket& socket,
0372  *     boost::asio::mutable_buffer buffer,
0373  *     CompletionToken&& token)
0374  *   -> decltype(
0375  *     boost::asio::async_initiate<CompletionToken,
0376  *       void(boost::system::error_code, std::size_t)>(
0377  *         boost::asio::composed(
0378  *           async_echo_implementation{socket, buffer,
0379  *             async_echo_implementation::starting}, socket),
0380  *         token))
0381  * {
0382  *   return boost::asio::async_initiate<CompletionToken,
0383  *     void(boost::system::error_code, std::size_t)>(
0384  *       boost::asio::composed(
0385  *         async_echo_implementation{socket, buffer,
0386  *           async_echo_implementation::starting}, socket),
0387  *       token, boost::system::error_code{}, 0);
0388  * } @endcode
0389  */
0390 template <BOOST_ASIO_COMPLETION_SIGNATURE... Signatures,
0391     typename Implementation, typename... IoObjectsOrExecutors>
0392 inline auto composed(Implementation&& implementation,
0393     IoObjectsOrExecutors&&... io_objects_or_executors)
0394   -> decltype(
0395     detail::make_initiate_composed<Signatures...>(
0396       static_cast<Implementation&&>(implementation),
0397       detail::make_composed_io_executors(
0398         detail::get_composed_io_executor(
0399           static_cast<IoObjectsOrExecutors&&>(
0400             io_objects_or_executors))...)))
0401 {
0402   return detail::make_initiate_composed<Signatures...>(
0403       static_cast<Implementation&&>(implementation),
0404       detail::make_composed_io_executors(
0405         detail::get_composed_io_executor(
0406           static_cast<IoObjectsOrExecutors&&>(
0407             io_objects_or_executors))...));
0408 }
0409 
0410 } // namespace asio
0411 } // namespace boost
0412 
0413 #include <boost/asio/detail/pop_options.hpp>
0414 
0415 #endif // BOOST_ASIO_COMPOSE_HPP