13 Asynchronous model [async]

13.21 Class executor [async.executor]

The executor class provides a polymorphic wrapper for types that satisfy the Executor requirements ([async.reqmts.executor]).

namespace std {
namespace experimental {
namespace net {
inline namespace v1 {

  class executor
  {
  public:
    // [async.executor.cons], construct / copy / destroy:

    executor() noexcept;
    executor(nullptr_t) noexcept;
    executor(const executor& e) noexcept;
    executor(executor&& e) noexcept;
    template<class Executor> executor(Executor e);
    template<class Executor, class ProtoAllocator>
      executor(allocator_arg_t, const ProtoAllocator& a, Executor e);

    executor& operator=(const executor& e) noexcept;
    executor& operator=(executor&& e) noexcept;
    executor& operator=(nullptr_t) noexcept;
    template<class Executor> executor& operator=(Executor e);

    ~executor();

    // [async.executor.modifiers], executor modifiers:

    void swap(executor& other) noexcept;
    template<class Executor, class ProtoAllocator>
      void assign(Executor e, const ProtoAllocator& a);

    // [async.executor.ops], executor operations:

    execution_context& context() const noexcept;

    void on_work_started() const noexcept;
    void on_work_finished() const noexcept;

    template<class Func, class ProtoAllocator>
      void dispatch(Func&& f, const ProtoAllocator& a) const;
    template<class Func, class ProtoAllocator>
      void post(Func&& f, const ProtoAllocator& a) const;
    template<class Func, class ProtoAllocator>
      void defer(Func&& f, const ProtoAllocator& a) const;

    // [async.executor.capacity], executor capacity:

    explicit operator bool() const noexcept;

    // [async.executor.target], executor target access:

    const type_info& target_type() const noexcept;
    template<class Executor> Executor* target() noexcept;
    template<class Executor> const Executor* target() const noexcept;
  };

  // [async.executor.comparisons], executor comparisons:

  bool operator==(const executor& a, const executor& b) noexcept;
  bool operator==(const executor& e, nullptr_t) noexcept;
  bool operator==(nullptr_t, const executor& e) noexcept;
  bool operator!=(const executor& a, const executor& b) noexcept;
  bool operator!=(const executor& e, nullptr_t) noexcept;
  bool operator!=(nullptr_t, const executor& e) noexcept;

  // [async.executor.algo], executor specialized algorithms:

  void swap(executor& a, executor& b) noexcept;

} // inline namespace v1
} // namespace net
} // namespace experimental

  template<class Allocator>
    struct uses_allocator<experimental::net::v1::executor, Allocator>
      : true_type {};

} // namespace std

Class executor meets the requirements of Executor ([async.reqmts.executor]), DefaultConstructible (C++ 2014 [defaultconstructible]), and CopyAssignable (C++ 2014 [copyassignable]).

Note: To meet the noexcept requirements for executor copy constructors and move constructors, implementations can share a target between two or more executor objects.  — end note ]

The target is the executor object that is held by the wrapper.

13.21.1 executor constructors [async.executor.cons]

executor() noexcept;

Postconditions: !*this.

executor(nullptr_t) noexcept;

Postconditions: !*this.

executor(const executor& e) noexcept;

Postconditions: !*this if !e; otherwise, *this targets e.target() or a copy of e.target().

executor(executor&& e) noexcept;

Effects: If !e, *this has no target; otherwise, moves e.target() or move-constructs the target of e into the target of *this, leaving e in a valid state with an unspecified value.

template<class Executor> executor(Executor e);

Effects: *this targets a copy of e initialized with std::move(e).

template<class Executor, class ProtoAllocator> executor(allocator_arg_t, const ProtoAllocator& a, Executor e);

Effects: *this targets a copy of e initialized with std::move(e).

A copy of the allocator argument is used to allocate memory, if necessary, for the internal data structures of the constructed executor object.

13.21.2 executor assignment [async.executor.assign]

executor& operator=(const executor& e) noexcept;

Effects: executor(e).swap(*this).

Returns: *this.

executor& operator=(executor&& e) noexcept;

Effects: Replaces the target of *this with the target of e, leaving e in a valid state with an unspecified value.

Returns: *this.

executor& operator=(nullptr_t) noexcept;

Effects: executor(nullptr).swap(*this).

Returns: *this.

template<class Executor> executor& operator=(Executor e);

Effects: executor(std::move(e)).swap(*this).

Returns: *this.

13.21.3 executor destructor [async.executor.dtor]

~executor();

Effects: If *this != nullptr, releases shared ownership of, or destroys, the target of *this.

13.21.4 executor modifiers [async.executor.modifiers]

void swap(executor& other) noexcept;

Effects: Interchanges the targets of *this and other.

template<class Executor, class ProtoAllocator> void assign(Executor e, const ProtoAllocator& a);

Effects: executor(allocator_arg, a, std::move(e)).swap(*this).

13.21.5 executor operations [async.executor.ops]

execution_context& context() const noexcept;

Requires: *this != nullptr.

Returns: e.context(), where e is the target object of *this.

void on_work_started() const noexcept;

Requires: *this != nullptr.

Effects: e.on_work_started(), where e is the target object of *this.

void on_work_finished() const noexcept;

Requires: *this != nullptr.

Effects: e.on_work_finished(), where e is the target object of *this.

template<class Func, class ProtoAllocator> void dispatch(Func&& f, const ProtoAllocator& a) const;

Let e be the target object of *this. Let a1 be the allocator that was specified when the target was set. Let fd be the result of DECAY_COPY(f) (C++ 2014 [thread.decaycopy]).

Effects: e.dispatch(g, a1), where g is a function object of unspecified type that, when called as g(), performs fd(). The allocator a is used to allocate any memory required to implement g.

template<class Func, class ProtoAllocator> void post(Func&& f, const ProtoAllocator& a) const;

Let e be the target object of *this. Let a1 be the allocator that was specified when the target was set. Let fd be the result of DECAY_COPY(f).

Effects: e.post(g, a1), where g is a function object of unspecified type that, when called as g(), performs fd(). The allocator a is used to allocate any memory required to implement g.

template<class Func, class ProtoAllocator> void defer(Func&& f, const ProtoAllocator& a) const;

Let e be the target object of *this. Let a1 be the allocator that was specified when the target was set. Let fd be the result of DECAY_COPY(f).

Effects: e.defer(g, a1), where g is a function object of unspecified type that, when called as g(), performs fd(). The allocator a is used to allocate any memory required to implement g.

13.21.6 executor capacity [async.executor.capacity]

explicit operator bool() const noexcept;

Returns: true if *this has a target, otherwise false.

13.21.7 executor target access [async.executor.target]

const type_info& target_type() const noexcept;

Returns: If *this has a target of type T, typeid(T); otherwise, typeid(void).

template<class Executor> Executor* target() noexcept; template<class Executor> const Executor* target() const noexcept;

Returns: If target_type() == typeid(Executor) a pointer to the stored executor target; otherwise a null pointer value.

13.21.8 executor comparisons [async.executor.comparisons]

bool operator==(const executor& a, const executor& b) noexcept;

Returns:

  • true if !a and !b;

  • true if a and b share a target;

  • true if e and f are the same type and e == f, where e is the target of a and f is the target of b;

  • otherwise false.

bool operator==(const executor& e, nullptr_t) noexcept; bool operator==(nullptr_t, const executor& e) noexcept;

Returns: !e.

bool operator!=(const executor& a, const executor& b) noexcept;

Returns: !(a == b).

bool operator!=(const executor& e, nullptr_t) noexcept; bool operator!=(nullptr_t, const executor& e) noexcept;

Returns: (bool) e.

13.21.9 executor specialized algorithms [async.executor.algo]

void swap(executor& a, executor& b) noexcept;

Effects: a.swap(b).