Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:44:27

0001 //
0002 // Copyright (c) 2023 Klemens Morgenstern (klemens.morgenstern@gmx.net)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_COBALT_HANDLE_HPP
0009 #define BOOST_COBALT_HANDLE_HPP
0010 
0011 #include <boost/asio/associator.hpp>
0012 #include <coroutine>
0013 #include <memory>
0014 
0015 namespace boost::cobalt
0016 {
0017 
0018 template<typename T>
0019 struct unique_handle
0020 {
0021   unique_handle() noexcept = default;
0022 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0023   explicit unique_handle(T * promise,
0024                          const boost::source_location & loc = BOOST_CURRENT_LOCATION) noexcept : handle_(promise), loc_(loc) {}
0025 #else
0026   explicit unique_handle(T * promise) noexcept : handle_(promise) {}
0027 #endif
0028   unique_handle(std::nullptr_t) noexcept {}
0029 
0030   std::coroutine_handle<T> release()
0031   {
0032     return std::coroutine_handle<T>::from_promise(*handle_.release());
0033   }
0034 
0035   void* address() const noexcept { return get_handle_().address(); }
0036 
0037 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0038   static unique_handle from_address(
0039       void* a,
0040       const boost::source_location & loc = BOOST_CURRENT_LOCATION) noexcept
0041   {
0042     unique_handle res;
0043     res.loc_ = loc;
0044     res.handle_.reset(&std::coroutine_handle<T>::from_address(a).promise());
0045     return res;
0046   }
0047 #else
0048   static unique_handle from_address(void* a) noexcept
0049   {
0050     unique_handle res;
0051     res.handle_.reset(&std::coroutine_handle<T>::from_address(a).promise());
0052     return res;
0053   }
0054 #endif
0055 
0056 
0057   bool done() const noexcept { return get_handle_().done(); }
0058   explicit operator bool() const { return static_cast<bool>(handle_); }
0059 
0060   void destroy() { handle_.reset(); }
0061 
0062   void operator()() const &
0063   {
0064 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0065     BOOST_ASIO_HANDLER_LOCATION((loc_.file_name(), loc_.line(), loc_.function_name()));
0066 #endif
0067     resume();
0068   }
0069   void resume()     const & { get_handle_().resume(); }
0070 
0071   void operator()() &&
0072   {
0073 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0074     BOOST_ASIO_HANDLER_LOCATION((loc_.file_name(), loc_.line(), loc_.function_name()));
0075 #endif
0076     release().resume();
0077   }
0078   void resume()     && { release().resume(); }
0079 
0080   T & promise() {return *handle_;}
0081 
0082 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0083   constexpr static unique_handle from_promise(
0084       T &p,
0085       const boost::source_location & loc = BOOST_CURRENT_LOCATION) noexcept
0086   {
0087     unique_handle res;
0088     res.loc_ = loc;
0089     res.handle_.reset(&p);
0090     return res;
0091   }
0092 #else
0093   constexpr static unique_handle from_promise(T &p) noexcept
0094   {
0095     unique_handle res;
0096     res.handle_.reset(&p);
0097     return res;
0098   }
0099 #endif
0100 
0101         T & operator*()       {return *handle_;}
0102   const T & operator*() const {return *handle_;}
0103 
0104 
0105         T * operator->()       {return handle_.get();}
0106   const T * operator->() const {return handle_.get();}
0107 
0108         T * get()        {return handle_.get();}
0109   const T * get() const  {return handle_.get();}
0110 
0111 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0112   void reset(T * handle = nullptr,
0113              const boost::source_location & loc = BOOST_CURRENT_LOCATION)
0114   {
0115     loc_ = loc; handle_.reset(handle);
0116   }
0117 #else
0118   void reset(T * handle = nullptr) {handle_.reset(handle);}
0119 #endif
0120 
0121   friend
0122   auto operator==(const unique_handle & h, std::nullptr_t) {return h.handle_ == nullptr;}
0123   friend
0124   auto operator!=(const unique_handle & h, std::nullptr_t) {return h.handle_ != nullptr;}
0125 
0126  private:
0127   struct deleter_
0128   {
0129     void operator()(T * p)
0130     {
0131       std::coroutine_handle<T>::from_promise(*p).destroy();
0132     }
0133   };
0134 
0135   std::coroutine_handle<T> get_handle_() const
0136   {
0137     return std::coroutine_handle<T>::from_promise(*handle_);
0138   }
0139 
0140   std::unique_ptr<T, deleter_> handle_;
0141 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0142   boost::source_location loc_;
0143 #endif
0144 };
0145 
0146 template<>
0147 struct unique_handle<void>
0148 {
0149   unique_handle() noexcept = default;
0150   unique_handle(std::nullptr_t) noexcept {}
0151 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0152   explicit unique_handle(void * handle,
0153                          const boost::source_location & loc = BOOST_CURRENT_LOCATION)  noexcept : handle_(handle), loc_(loc) {}
0154 #else
0155   explicit unique_handle(void * handle)  noexcept : handle_(handle) {}
0156 #endif
0157   std::coroutine_handle<void> release()
0158   {
0159     return std::coroutine_handle<void>::from_address(handle_.release());
0160   }
0161   void* address() const noexcept { return get_handle_().address(); }
0162 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0163   static unique_handle<void> from_address(void* a,
0164                                           const boost::source_location & loc = BOOST_CURRENT_LOCATION) noexcept
0165   {
0166 
0167     unique_handle res;
0168     res.loc_ = loc;
0169     res.handle_.reset(std::coroutine_handle<void>::from_address(a).address());
0170     return res;
0171   }
0172 #else
0173 static unique_handle<void> from_address(void* a) noexcept
0174   {
0175 
0176     unique_handle res;
0177     res.handle_.reset(std::coroutine_handle<void>::from_address(a).address());
0178     return res;
0179   }
0180 #endif
0181 
0182   explicit operator bool() const { return static_cast<bool>(handle_); }
0183   bool done() const noexcept { return get_handle_().done(); }
0184 
0185   void operator()() const &
0186   {
0187 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0188     BOOST_ASIO_HANDLER_LOCATION((loc_.file_name(), loc_.line(), loc_.function_name()));
0189 #endif
0190     resume();
0191   }
0192   void resume() const & { get_handle_().resume(); }
0193 
0194   void operator()() &&
0195   {
0196 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0197     BOOST_ASIO_HANDLER_LOCATION((loc_.file_name(), loc_.line(), loc_.function_name()));
0198 #endif
0199     release().resume();
0200   }
0201   void resume()     && { release().resume(); }
0202 
0203   void destroy() { handle_.reset(); }
0204 
0205         void * get()       { return handle_.get(); }
0206   const void * get() const { return handle_.get(); }
0207 
0208 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0209   void reset(void * handle = nullptr,
0210              const boost::source_location & loc = BOOST_CURRENT_LOCATION)
0211   {
0212     loc_ = loc;
0213     handle_.reset(handle);
0214   }
0215 #else
0216   void reset(void * handle = nullptr) {handle_.reset(handle);}
0217 #endif
0218 
0219   friend
0220   auto operator==(const unique_handle & h, std::nullptr_t) {return h.handle_ == nullptr;}
0221   friend
0222   auto operator!=(const unique_handle & h, std::nullptr_t) {return h.handle_ != nullptr;}
0223  private:
0224   struct deleter_
0225   {
0226     void operator()(void * p)
0227     {
0228       std::coroutine_handle<void>::from_address(p).destroy();
0229     }
0230   };
0231 
0232   std::coroutine_handle<void> get_handle_() const
0233   {
0234     return std::coroutine_handle<void>::from_address(handle_.get());
0235   }
0236 
0237   std::unique_ptr<void, deleter_> handle_;
0238 #if defined(BOOST_ASIO_ENABLE_HANDLER_TRACKING)
0239   boost::source_location loc_;
0240 #endif
0241 };
0242 
0243 template<>
0244 struct unique_handle<std::noop_coroutine_promise>
0245 {
0246   unique_handle() noexcept = default;
0247   unique_handle(std::nullptr_t) noexcept {}
0248 
0249   std::coroutine_handle<void> release()
0250   {
0251     return std::noop_coroutine();
0252   }
0253   void* address() const noexcept { return std::noop_coroutine().address(); }
0254   bool done() const noexcept { return true;}
0255   void operator()() const {}
0256   void resume() const {}
0257   void destroy() {}
0258   explicit operator bool() const { return true; }
0259 
0260   struct executor_type
0261   {
0262     template<typename Fn>
0263     void execute(Fn &&) const {}
0264   };
0265 
0266   executor_type get_executor() const {return {}; }
0267 
0268   friend
0269   auto operator==(const unique_handle &, std::nullptr_t) {return false;}
0270   friend
0271   auto operator!=(const unique_handle &, std::nullptr_t) {return true;}
0272 };
0273 
0274 }
0275 
0276 namespace boost::asio
0277 {
0278 
0279 template <template <typename, typename> class Associator,
0280     typename Promise, typename DefaultCandidate>
0281     requires (!std::is_void_v<Promise>)
0282 struct associator<Associator,
0283     boost::cobalt::unique_handle<Promise>, DefaultCandidate>
0284   : Associator<Promise, DefaultCandidate>
0285 {
0286   static typename Associator<Promise, DefaultCandidate>::type
0287   get(const boost::cobalt::unique_handle<Promise>& h) BOOST_ASIO_NOEXCEPT
0288   {
0289     return Associator<Promise, DefaultCandidate>::get(*h);
0290   }
0291 
0292   static BOOST_ASIO_AUTO_RETURN_TYPE_PREFIX2(
0293       typename Associator<Handler, DefaultCandidate>::type)
0294   get(const boost::cobalt::unique_handle<Promise>& h,
0295       const DefaultCandidate& c) BOOST_ASIO_NOEXCEPT
0296     BOOST_ASIO_AUTO_RETURN_TYPE_SUFFIX((
0297       Associator<Promise, DefaultCandidate>::get(*h, c)))
0298   {
0299     return Associator<Promise, DefaultCandidate>::get(*h, c);
0300   }
0301 };
0302 
0303 }
0304 
0305 
0306 #endif //BOOST_COBALT_HANDLE_HPP