summaryrefslogtreecommitdiffstats
path: root/lib/asio/impl/executor.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/asio/impl/executor.hpp')
-rw-r--r--lib/asio/impl/executor.hpp386
1 files changed, 386 insertions, 0 deletions
diff --git a/lib/asio/impl/executor.hpp b/lib/asio/impl/executor.hpp
new file mode 100644
index 0000000..0fcf5f5
--- /dev/null
+++ b/lib/asio/impl/executor.hpp
@@ -0,0 +1,386 @@
+//
+// impl/executor.hpp
+// ~~~~~~~~~~~~~~~~~
+//
+// Copyright (c) 2003-2018 Christopher M. Kohlhoff (chris at kohlhoff dot com)
+//
+// Distributed under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+//
+
+#ifndef ASIO_IMPL_EXECUTOR_HPP
+#define ASIO_IMPL_EXECUTOR_HPP
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1200)
+# pragma once
+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)
+
+#include "asio/detail/config.hpp"
+#include "asio/detail/atomic_count.hpp"
+#include "asio/detail/executor_op.hpp"
+#include "asio/detail/global.hpp"
+#include "asio/detail/memory.hpp"
+#include "asio/detail/recycling_allocator.hpp"
+#include "asio/executor.hpp"
+#include "asio/system_executor.hpp"
+
+#include "asio/detail/push_options.hpp"
+
+namespace asio {
+
+#if !defined(GENERATING_DOCUMENTATION)
+
+#if defined(ASIO_HAS_MOVE)
+
+// Lightweight, move-only function object wrapper.
+class executor::function
+{
+public:
+ template <typename F, typename Alloc>
+ explicit function(F f, const Alloc& a)
+ {
+ // Allocate and construct an operation to wrap the function.
+ typedef detail::executor_op<F, Alloc> op;
+ typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };
+ op_ = new (p.v) op(ASIO_MOVE_CAST(F)(f), a);
+ p.v = 0;
+ }
+
+ function(function&& other)
+ : op_(other.op_)
+ {
+ other.op_ = 0;
+ }
+
+ ~function()
+ {
+ if (op_)
+ op_->destroy();
+ }
+
+ void operator()()
+ {
+ if (op_)
+ {
+ detail::scheduler_operation* op = op_;
+ op_ = 0;
+ op->complete(this, asio::error_code(), 0);
+ }
+ }
+
+private:
+ detail::scheduler_operation* op_;
+};
+
+#else // defined(ASIO_HAS_MOVE)
+
+// Not so lightweight, copyable function object wrapper.
+class executor::function
+{
+public:
+ template <typename F, typename Alloc>
+ explicit function(const F& f, const Alloc&)
+ : impl_(new impl<F>(f))
+ {
+ }
+
+ void operator()()
+ {
+ impl_->invoke_(impl_.get());
+ }
+
+private:
+ // Base class for polymorphic function implementations.
+ struct impl_base
+ {
+ void (*invoke_)(impl_base*);
+ };
+
+ // Polymorphic function implementation.
+ template <typename F>
+ struct impl : impl_base
+ {
+ impl(const F& f)
+ : function_(f)
+ {
+ invoke_ = &function::invoke<F>;
+ }
+
+ F function_;
+ };
+
+ // Helper to invoke a function.
+ template <typename F>
+ static void invoke(impl_base* i)
+ {
+ static_cast<impl<F>*>(i)->function_();
+ }
+
+ detail::shared_ptr<impl_base> impl_;
+};
+
+#endif // defined(ASIO_HAS_MOVE)
+
+// Default polymorphic allocator implementation.
+template <typename Executor, typename Allocator>
+class executor::impl
+ : public executor::impl_base
+{
+public:
+ typedef ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;
+
+ static impl_base* create(const Executor& e, Allocator a = Allocator())
+ {
+ raw_mem mem(a);
+ impl* p = new (mem.ptr_) impl(e, a);
+ mem.ptr_ = 0;
+ return p;
+ }
+
+ impl(const Executor& e, const Allocator& a) ASIO_NOEXCEPT
+ : impl_base(false),
+ ref_count_(1),
+ executor_(e),
+ allocator_(a)
+ {
+ }
+
+ impl_base* clone() const ASIO_NOEXCEPT
+ {
+ ++ref_count_;
+ return const_cast<impl_base*>(static_cast<const impl_base*>(this));
+ }
+
+ void destroy() ASIO_NOEXCEPT
+ {
+ if (--ref_count_ == 0)
+ {
+ allocator_type alloc(allocator_);
+ impl* p = this;
+ p->~impl();
+ alloc.deallocate(p, 1);
+ }
+ }
+
+ void on_work_started() ASIO_NOEXCEPT
+ {
+ executor_.on_work_started();
+ }
+
+ void on_work_finished() ASIO_NOEXCEPT
+ {
+ executor_.on_work_finished();
+ }
+
+ execution_context& context() ASIO_NOEXCEPT
+ {
+ return executor_.context();
+ }
+
+ void dispatch(ASIO_MOVE_ARG(function) f)
+ {
+ executor_.dispatch(ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void post(ASIO_MOVE_ARG(function) f)
+ {
+ executor_.post(ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void defer(ASIO_MOVE_ARG(function) f)
+ {
+ executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ type_id_result_type target_type() const ASIO_NOEXCEPT
+ {
+ return type_id<Executor>();
+ }
+
+ void* target() ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ const void* target() const ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ bool equals(const impl_base* e) const ASIO_NOEXCEPT
+ {
+ if (this == e)
+ return true;
+ if (target_type() != e->target_type())
+ return false;
+ return executor_ == *static_cast<const Executor*>(e->target());
+ }
+
+private:
+ mutable detail::atomic_count ref_count_;
+ Executor executor_;
+ Allocator allocator_;
+
+ struct raw_mem
+ {
+ allocator_type allocator_;
+ impl* ptr_;
+
+ explicit raw_mem(const Allocator& a)
+ : allocator_(a),
+ ptr_(allocator_.allocate(1))
+ {
+ }
+
+ ~raw_mem()
+ {
+ if (ptr_)
+ allocator_.deallocate(ptr_, 1);
+ }
+
+ private:
+ // Disallow copying and assignment.
+ raw_mem(const raw_mem&);
+ raw_mem operator=(const raw_mem&);
+ };
+};
+
+// Polymorphic allocator specialisation for system_executor.
+template <typename Allocator>
+class executor::impl<system_executor, Allocator>
+ : public executor::impl_base
+{
+public:
+ static impl_base* create(const system_executor&,
+ const Allocator& = Allocator())
+ {
+ return &detail::global<impl<system_executor, std::allocator<void> > >();
+ }
+
+ impl()
+ : impl_base(true)
+ {
+ }
+
+ impl_base* clone() const ASIO_NOEXCEPT
+ {
+ return const_cast<impl_base*>(static_cast<const impl_base*>(this));
+ }
+
+ void destroy() ASIO_NOEXCEPT
+ {
+ }
+
+ void on_work_started() ASIO_NOEXCEPT
+ {
+ executor_.on_work_started();
+ }
+
+ void on_work_finished() ASIO_NOEXCEPT
+ {
+ executor_.on_work_finished();
+ }
+
+ execution_context& context() ASIO_NOEXCEPT
+ {
+ return executor_.context();
+ }
+
+ void dispatch(ASIO_MOVE_ARG(function) f)
+ {
+ executor_.dispatch(ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void post(ASIO_MOVE_ARG(function) f)
+ {
+ executor_.post(ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ void defer(ASIO_MOVE_ARG(function) f)
+ {
+ executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_);
+ }
+
+ type_id_result_type target_type() const ASIO_NOEXCEPT
+ {
+ return type_id<system_executor>();
+ }
+
+ void* target() ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ const void* target() const ASIO_NOEXCEPT
+ {
+ return &executor_;
+ }
+
+ bool equals(const impl_base* e) const ASIO_NOEXCEPT
+ {
+ return this == e;
+ }
+
+private:
+ system_executor executor_;
+ Allocator allocator_;
+};
+
+template <typename Executor>
+executor::executor(Executor e)
+ : impl_(impl<Executor, std::allocator<void> >::create(e))
+{
+}
+
+template <typename Executor, typename Allocator>
+executor::executor(allocator_arg_t, const Allocator& a, Executor e)
+ : impl_(impl<Executor, Allocator>::create(e, a))
+{
+}
+
+template <typename Function, typename Allocator>
+void executor::dispatch(ASIO_MOVE_ARG(Function) f,
+ const Allocator& a) const
+{
+ impl_base* i = get_impl();
+ if (i->fast_dispatch_)
+ system_executor().dispatch(ASIO_MOVE_CAST(Function)(f), a);
+ else
+ i->dispatch(function(ASIO_MOVE_CAST(Function)(f), a));
+}
+
+template <typename Function, typename Allocator>
+void executor::post(ASIO_MOVE_ARG(Function) f,
+ const Allocator& a) const
+{
+ get_impl()->post(function(ASIO_MOVE_CAST(Function)(f), a));
+}
+
+template <typename Function, typename Allocator>
+void executor::defer(ASIO_MOVE_ARG(Function) f,
+ const Allocator& a) const
+{
+ get_impl()->defer(function(ASIO_MOVE_CAST(Function)(f), a));
+}
+
+template <typename Executor>
+Executor* executor::target() ASIO_NOEXCEPT
+{
+ return impl_ && impl_->target_type() == type_id<Executor>()
+ ? static_cast<Executor*>(impl_->target()) : 0;
+}
+
+template <typename Executor>
+const Executor* executor::target() const ASIO_NOEXCEPT
+{
+ return impl_ && impl_->target_type() == type_id<Executor>()
+ ? static_cast<Executor*>(impl_->target()) : 0;
+}
+
+#endif // !defined(GENERATING_DOCUMENTATION)
+
+} // namespace asio
+
+#include "asio/detail/pop_options.hpp"
+
+#endif // ASIO_IMPL_EXECUTOR_HPP