diff options
Diffstat (limited to 'lib/asio/impl/executor.hpp')
| -rw-r--r-- | lib/asio/impl/executor.hpp | 386 | 
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 | 
