File indexing completed on 2025-01-18 09:28:55
0001
0002
0003
0004
0005
0006
0007
0008
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
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
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
0160 raw_mem(const raw_mem&);
0161 raw_mem operator=(const raw_mem&);
0162 };
0163 };
0164
0165
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
0311
0312 }
0313 }
0314
0315 #include <boost/asio/detail/pop_options.hpp>
0316
0317 #endif
0318
0319 #endif