Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:28:55

0001 //
0002 // impl/executor.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_IMPL_EXECUTOR_HPP
0012 #define BOOST_ASIO_IMPL_EXECUTOR_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 
0020 #if !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0021 
0022 #include <new>
0023 #include <boost/asio/detail/atomic_count.hpp>
0024 #include <boost/asio/detail/global.hpp>
0025 #include <boost/asio/detail/memory.hpp>
0026 #include <boost/asio/executor.hpp>
0027 #include <boost/asio/system_executor.hpp>
0028 
0029 #include <boost/asio/detail/push_options.hpp>
0030 
0031 namespace boost {
0032 namespace asio {
0033 
0034 #if !defined(GENERATING_DOCUMENTATION)
0035 
0036 // Default polymorphic executor implementation.
0037 template <typename Executor, typename Allocator>
0038 class executor::impl
0039   : public executor::impl_base
0040 {
0041 public:
0042   typedef BOOST_ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
0043 
0044   static impl_base* create(const Executor& e, Allocator a = Allocator())
0045   {
0046     raw_mem mem(a);
0047     impl* p = new (mem.ptr_) impl(e, a);
0048     mem.ptr_ = 0;
0049     return p;
0050   }
0051 
0052   static impl_base* create(std::nothrow_t, const Executor& e) noexcept
0053   {
0054     return new (std::nothrow) impl(e, std::allocator<void>());
0055   }
0056 
0057   impl(const Executor& e, const Allocator& a) noexcept
0058     : impl_base(false),
0059       ref_count_(1),
0060       executor_(e),
0061       allocator_(a)
0062   {
0063   }
0064 
0065   impl_base* clone() const noexcept
0066   {
0067     detail::ref_count_up(ref_count_);
0068     return const_cast<impl_base*>(static_cast<const impl_base*>(this));
0069   }
0070 
0071   void destroy() noexcept
0072   {
0073     if (detail::ref_count_down(ref_count_))
0074     {
0075       allocator_type alloc(allocator_);
0076       impl* p = this;
0077       p->~impl();
0078       alloc.deallocate(p, 1);
0079     }
0080   }
0081 
0082   void on_work_started() noexcept
0083   {
0084     executor_.on_work_started();
0085   }
0086 
0087   void on_work_finished() noexcept
0088   {
0089     executor_.on_work_finished();
0090   }
0091 
0092   execution_context& context() noexcept
0093   {
0094     return executor_.context();
0095   }
0096 
0097   void dispatch(function&& f)
0098   {
0099     executor_.dispatch(static_cast<function&&>(f), allocator_);
0100   }
0101 
0102   void post(function&& f)
0103   {
0104     executor_.post(static_cast<function&&>(f), allocator_);
0105   }
0106 
0107   void defer(function&& f)
0108   {
0109     executor_.defer(static_cast<function&&>(f), allocator_);
0110   }
0111 
0112   type_id_result_type target_type() const noexcept
0113   {
0114     return type_id<Executor>();
0115   }
0116 
0117   void* target() noexcept
0118   {
0119     return &executor_;
0120   }
0121 
0122   const void* target() const noexcept
0123   {
0124     return &executor_;
0125   }
0126 
0127   bool equals(const impl_base* e) const noexcept
0128   {
0129     if (this == e)
0130       return true;
0131     if (target_type() != e->target_type())
0132       return false;
0133     return executor_ == *static_cast<const Executor*>(e->target());
0134   }
0135 
0136 private:
0137   mutable detail::atomic_count ref_count_;
0138   Executor executor_;
0139   Allocator allocator_;
0140 
0141   struct raw_mem
0142   {
0143     allocator_type allocator_;
0144     impl* ptr_;
0145 
0146     explicit raw_mem(const Allocator& a)
0147       : allocator_(a),
0148         ptr_(allocator_.allocate(1))
0149     {
0150     }
0151 
0152     ~raw_mem()
0153     {
0154       if (ptr_)
0155         allocator_.deallocate(ptr_, 1);
0156     }
0157 
0158   private:
0159     // Disallow copying and assignment.
0160     raw_mem(const raw_mem&);
0161     raw_mem operator=(const raw_mem&);
0162   };
0163 };
0164 
0165 // Polymorphic executor specialisation for system_executor.
0166 template <typename Allocator>
0167 class executor::impl<system_executor, Allocator>
0168   : public executor::impl_base
0169 {
0170 public:
0171   static impl_base* create(const system_executor&,
0172       const Allocator& = Allocator())
0173   {
0174     return &detail::global<impl<system_executor, std::allocator<void>> >();
0175   }
0176 
0177   static impl_base* create(std::nothrow_t, const system_executor&) noexcept
0178   {
0179     return &detail::global<impl<system_executor, std::allocator<void>> >();
0180   }
0181 
0182   impl()
0183     : impl_base(true)
0184   {
0185   }
0186 
0187   impl_base* clone() const noexcept
0188   {
0189     return const_cast<impl_base*>(static_cast<const impl_base*>(this));
0190   }
0191 
0192   void destroy() noexcept
0193   {
0194   }
0195 
0196   void on_work_started() noexcept
0197   {
0198     executor_.on_work_started();
0199   }
0200 
0201   void on_work_finished() noexcept
0202   {
0203     executor_.on_work_finished();
0204   }
0205 
0206   execution_context& context() noexcept
0207   {
0208     return executor_.context();
0209   }
0210 
0211   void dispatch(function&& f)
0212   {
0213     executor_.dispatch(static_cast<function&&>(f),
0214         std::allocator<void>());
0215   }
0216 
0217   void post(function&& f)
0218   {
0219     executor_.post(static_cast<function&&>(f),
0220         std::allocator<void>());
0221   }
0222 
0223   void defer(function&& f)
0224   {
0225     executor_.defer(static_cast<function&&>(f),
0226         std::allocator<void>());
0227   }
0228 
0229   type_id_result_type target_type() const noexcept
0230   {
0231     return type_id<system_executor>();
0232   }
0233 
0234   void* target() noexcept
0235   {
0236     return &executor_;
0237   }
0238 
0239   const void* target() const noexcept
0240   {
0241     return &executor_;
0242   }
0243 
0244   bool equals(const impl_base* e) const noexcept
0245   {
0246     return this == e;
0247   }
0248 
0249 private:
0250   system_executor executor_;
0251 };
0252 
0253 template <typename Executor>
0254 executor::executor(Executor e)
0255   : impl_(impl<Executor, std::allocator<void>>::create(e))
0256 {
0257 }
0258 
0259 template <typename Executor>
0260 executor::executor(std::nothrow_t, Executor e) noexcept
0261   : impl_(impl<Executor, std::allocator<void>>::create(std::nothrow, e))
0262 {
0263 }
0264 
0265 template <typename Executor, typename Allocator>
0266 executor::executor(allocator_arg_t, const Allocator& a, Executor e)
0267   : impl_(impl<Executor, Allocator>::create(e, a))
0268 {
0269 }
0270 
0271 template <typename Function, typename Allocator>
0272 void executor::dispatch(Function&& f,
0273     const Allocator& a) const
0274 {
0275   impl_base* i = get_impl();
0276   if (i->fast_dispatch_)
0277     system_executor().dispatch(static_cast<Function&&>(f), a);
0278   else
0279     i->dispatch(function(static_cast<Function&&>(f), a));
0280 }
0281 
0282 template <typename Function, typename Allocator>
0283 void executor::post(Function&& f,
0284     const Allocator& a) const
0285 {
0286   get_impl()->post(function(static_cast<Function&&>(f), a));
0287 }
0288 
0289 template <typename Function, typename Allocator>
0290 void executor::defer(Function&& f,
0291     const Allocator& a) const
0292 {
0293   get_impl()->defer(function(static_cast<Function&&>(f), a));
0294 }
0295 
0296 template <typename Executor>
0297 Executor* executor::target() noexcept
0298 {
0299   return impl_ && impl_->target_type() == type_id<Executor>()
0300     ? static_cast<Executor*>(impl_->target()) : 0;
0301 }
0302 
0303 template <typename Executor>
0304 const Executor* executor::target() const noexcept
0305 {
0306   return impl_ && impl_->target_type() == type_id<Executor>()
0307     ? static_cast<Executor*>(impl_->target()) : 0;
0308 }
0309 
0310 #endif // !defined(GENERATING_DOCUMENTATION)
0311 
0312 } // namespace asio
0313 } // namespace boost
0314 
0315 #include <boost/asio/detail/pop_options.hpp>
0316 
0317 #endif // !defined(BOOST_ASIO_NO_TS_EXECUTORS)
0318 
0319 #endif // BOOST_ASIO_IMPL_EXECUTOR_HPP