// <experimental/executor> -*- C++ -*-

// Copyright (C) 2015-2021 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library.  This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.

// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// Under Section 7 of GPL version 3, you are granted additional
// permissions described in the GCC Runtime Library Exception, version
// 3.1, as published by the Free Software Foundation.

// You should have received a copy of the GNU General Public License and
// a copy of the GCC Runtime Library Exception along with this program;
// see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
// <http://www.gnu.org/licenses/>.

/** @file experimental/executor
 *  This is a TS C++ Library header.
 *  @ingroup networking-ts
 */

#ifndef _GLIBCXX_EXPERIMENTAL_EXECUTOR
#define _GLIBCXX_EXPERIMENTAL_EXECUTOR 1

#pragma GCC system_header

#if __cplusplus >= 201402L

#include <algorithm>
#include <condition_variable>
#include <functional>
#include <future>
#include <list>
#include <queue>
#include <thread>
#include <tuple>
#include <unordered_map>
#include <experimental/netfwd>
#include <bits/unique_ptr.h>
#include <experimental/bits/net.h>

namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
namespace experimental
{
namespace net
{
inline namespace v1
{

  /** @addtogroup networking-ts
   *  @{
   */

  /// Customization point for asynchronous operations.
  template<typename _CompletionToken, typename _Signature, typename = void>
    class async_result;

  /// Convenience utility to help implement asynchronous operations.
  template<typename _CompletionToken, typename _Signature>
    class async_completion;

  template<typename _Tp, typename _ProtoAlloc, typename = __void_t<>>
    struct __associated_allocator_impl
    {
      using type = _ProtoAlloc;

      static type
      _S_get(const _Tp&, const _ProtoAlloc& __a) noexcept { return __a; }
    };

  template<typename _Tp, typename _ProtoAlloc>
    struct __associated_allocator_impl<_Tp, _ProtoAlloc,
				       __void_t<typename _Tp::allocator_type>>
    {
      using type = typename _Tp::allocator_type;

      static type
      _S_get(const _Tp& __t, const _ProtoAlloc&) noexcept
      { return __t.get_allocator(); }
    };

  /// Helper to associate an allocator with a type.
  template<typename _Tp, typename _ProtoAllocator = allocator<void>>
    struct associated_allocator
    : __associated_allocator_impl<_Tp, _ProtoAllocator>
    {
      static auto
      get(const _Tp& __t,
	  const _ProtoAllocator& __a = _ProtoAllocator()) noexcept
      {
	using _Impl = __associated_allocator_impl<_Tp, _ProtoAllocator>;
	return _Impl::_S_get(__t, __a);
      }
    };

  /// Alias template for associated_allocator.
  template<typename _Tp, typename _ProtoAllocator = allocator<void>>
    using associated_allocator_t
      = typename associated_allocator<_Tp, _ProtoAllocator>::type;

  // get_associated_allocator:

  template<typename _Tp>
    inline associated_allocator_t<_Tp>
    get_associated_allocator(const _Tp& __t) noexcept
    { return associated_allocator<_Tp>::get(__t); }

  template<typename _Tp, typename _ProtoAllocator>
    inline associated_allocator_t<_Tp, _ProtoAllocator>
    get_associated_allocator(const _Tp& __t,
			     const _ProtoAllocator& __a) noexcept
    { return associated_allocator<_Tp, _ProtoAllocator>::get(__t, __a); }

  enum class fork_event { prepare, parent, child };

  /// An extensible, type-safe, polymorphic set of services.
  class execution_context;

  class service_already_exists : public logic_error
  {
  public:
    // _GLIBCXX_RESOLVE_LIB_DEFECTS
    // 3414. service_already_exists has no usable constructors
    service_already_exists() : logic_error("service already exists") { }
  };

  template<typename _Tp> struct is_executor;

  struct executor_arg_t { };

  constexpr executor_arg_t executor_arg = executor_arg_t();

  /// Trait for determining whether to construct an object with an executor.
  template<typename _Tp, typename _Executor> struct uses_executor;

  template<typename _Tp, typename _Executor, typename = __void_t<>>
    struct __associated_executor_impl
    {
      using type = _Executor;

      static type
      _S_get(const _Tp&, const _Executor& __e) noexcept { return __e; }
    };

  template<typename _Tp, typename _Executor>
    struct __associated_executor_impl<_Tp, _Executor,
				       __void_t<typename _Tp::executor_type>>
    {
      using type = typename _Tp::executor_type;

      static type
      _S_get(const _Tp& __t, const _Executor&) noexcept
      { return __t.get_executor(); }
    };

  /// Helper to associate an executor with a type.
  template<typename _Tp, typename _Executor = system_executor>
    struct associated_executor
    : __associated_executor_impl<_Tp, _Executor>
    {
      static auto
      get(const _Tp& __t, const _Executor& __e = _Executor()) noexcept
      { return __associated_executor_impl<_Tp, _Executor>::_S_get(__t, __e); }
    };


  template<typename _Tp, typename _Executor = system_executor>
    using associated_executor_t
      = typename associated_executor<_Tp, _Executor>::type;

  template<typename _ExecutionContext>
    using __is_exec_context
      = is_convertible<_ExecutionContext&, execution_context&>;

  template<typename _Tp>
    using __executor_t = typename _Tp::executor_type;

  // get_associated_executor:

  template<typename _Tp>
    inline associated_executor_t<_Tp>
    get_associated_executor(const _Tp& __t) noexcept
    { return associated_executor<_Tp>::get(__t); }

  template<typename _Tp, typename _Executor>
    inline
    enable_if_t<is_executor<_Executor>::value,
		associated_executor_t<_Tp, _Executor>>
    get_associated_executor(const _Tp& __t, const _Executor& __ex)
    { return associated_executor<_Tp, _Executor>::get(__t, __ex); }

  template<typename _Tp, typename _ExecutionContext>
    inline
    enable_if_t<__is_exec_context<_ExecutionContext>::value,
		associated_executor_t<_Tp, __executor_t<_ExecutionContext>>>
    get_associated_executor(const _Tp& __t, _ExecutionContext& __ctx) noexcept
    { return net::get_associated_executor(__t, __ctx.get_executor()); }


  /// Helper to bind an executor to an object or function.
  template<typename _Tp, typename _Executor>
    class executor_binder;

  template<typename _Tp, typename _Executor, typename _Signature>
    class async_result<executor_binder<_Tp, _Executor>, _Signature>;

  template<typename _Tp, typename _Executor, typename _ProtoAllocator>
    struct associated_allocator<executor_binder<_Tp, _Executor>,
				_ProtoAllocator>;

  template<typename _Tp, typename _Executor, typename _Executor1>
    struct associated_executor<executor_binder<_Tp, _Executor>, _Executor1>;

  // bind_executor:

  template<typename _Executor, typename _Tp>
    inline
    enable_if_t<is_executor<_Executor>::value,
		executor_binder<decay_t<_Tp>, _Executor>>
    bind_executor(const _Executor& __ex, _Tp&& __t)
    { return { std::forward<_Tp>(__t), __ex }; }

  template<typename _ExecutionContext, typename _Tp>
    inline
    enable_if_t<__is_exec_context<_ExecutionContext>::value,
		executor_binder<decay_t<_Tp>, __executor_t<_ExecutionContext>>>
    bind_executor(_ExecutionContext& __ctx, _Tp&& __t)
    { return { __ctx.get_executor(), forward<_Tp>(__t) }; }


  /// A scope-guard type to record when work is started and finished.
  template<typename _Executor>
    class executor_work_guard;

  // make_work_guard:

  template<typename _Executor>
    inline
    enable_if_t<is_executor<_Executor>::value, executor_work_guard<_Executor>>
    make_work_guard(const _Executor& __ex)
    { return executor_work_guard<_Executor>(__ex); }

  template<typename _ExecutionContext>
    inline
    enable_if_t<__is_exec_context<_ExecutionContext>::value,
		executor_work_guard<__executor_t<_ExecutionContext>>>
    make_work_guard(_ExecutionContext& __ctx)
    { return net::make_work_guard(__ctx.get_executor()); }

  template<typename _Tp>
    inline
    enable_if_t<__not_<__or_<is_executor<_Tp>, __is_exec_context<_Tp>>>::value,
		executor_work_guard<associated_executor_t<_Tp>>>
    make_work_guard(const _Tp& __t)
    { return net::get_associated_executor(__t); }

  template<typename _Tp, typename _Up>
    auto
    make_work_guard(const _Tp& __t, _Up&& __u)
    -> decltype(net::make_work_guard(
	  net::get_associated_executor(__t, forward<_Up>(__u))))
    {
      return net::make_work_guard(
	  net::get_associated_executor(__t, forward<_Up>(__u)));
    }

  /// Allows function objects to execute on any thread.
  class system_executor;

  /// The execution context associated with system_executor objects.
  class system_context;

  inline bool
  operator==(const system_executor&, const system_executor&) { return true; }

  inline bool
  operator!=(const system_executor&, const system_executor&) { return false; }

  /// Exception thrown by empty executors.
  class bad_executor;

  /// Polymorphic wrapper for types satisfying the Executor requirements.
  class executor;

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

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

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

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

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

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

  void swap(executor&, executor&) noexcept;

  // dispatch:

  template<typename _CompletionToken>
    __deduced_t<_CompletionToken, void()>
    dispatch(_CompletionToken&& __token);

  template<typename _Executor, typename _CompletionToken>
    __deduced_t<_CompletionToken, void()>
    dispatch(const _Executor& __ex, _CompletionToken&& __token);

  template<typename _ExecutionContext, typename _CompletionToken>
    __deduced_t<_CompletionToken, void()>
    dispatch(_ExecutionContext& __ctx, _CompletionToken&& __token);

  // post:

  template<typename _CompletionToken>
    __deduced_t<_CompletionToken, void()>
    post(_CompletionToken&& __token);
  template<typename _Executor, typename _CompletionToken>
    enable_if_t<is_executor<_Executor>::value,
		__deduced_t<_CompletionToken, void()>>
    post(const _Executor& __ex, _CompletionToken&& __token);
  template<typename _ExecutionContext, typename _CompletionToken>
    enable_if_t<__is_exec_context<_ExecutionContext>::value,
		__deduced_t<_CompletionToken, void()>>
    post(_ExecutionContext& __ctx, _CompletionToken&& __token);

  // defer:

  template<typename _CompletionToken>
    __deduced_t<_CompletionToken, void()>
    defer(_CompletionToken&& __token);
  template<typename _Executor, typename _CompletionToken>
    __deduced_t<_CompletionToken, void()>
    defer(const _Executor& __ex, _CompletionToken&& __token);
  template<typename _ExecutionContext, typename _CompletionToken>
    __deduced_t<_CompletionToken, void()>
    defer(_ExecutionContext& __ctx, _CompletionToken&& __token);

  template<typename _Executor>
    class strand;

  template<typename _Executor>
    bool
    operator==(const strand<_Executor>& __a, const strand<_Executor>& __b);

  template<typename _Executor>
    bool
    operator!=(const strand<_Executor>& __a, const strand<_Executor>& __b)
    { return !(__a == __b); }

  template<typename _CompletionToken, typename _Signature, typename>
    class async_result
    {
    public:
      using completion_handler_type = _CompletionToken;
      using return_type = void;

      explicit async_result(completion_handler_type&) {}
      async_result(const async_result&) = delete;
      async_result& operator=(const async_result&) = delete;

      return_type get() {}
    };

  template<typename _CompletionToken, typename _Signature>
    class async_completion
    {
      using __result_type
	= async_result<decay_t<_CompletionToken>, _Signature>;

    public:
      using completion_handler_type
	= typename __result_type::completion_handler_type;

    private:
      using __handler_type = __conditional_t<
	is_same<_CompletionToken, completion_handler_type>::value,
	completion_handler_type&,
	completion_handler_type>;

    public:
      explicit
      async_completion(_CompletionToken& __t)
      : completion_handler(std::forward<__handler_type>(__t)),
	result(completion_handler)
      { }

      async_completion(const async_completion&) = delete;
      async_completion& operator=(const async_completion&) = delete;

      __handler_type	completion_handler;
      __result_type	result;
    };


  class execution_context
  {
  public:
    class service
    {
    protected:
      // construct / copy / destroy:

      explicit
      service(execution_context& __owner) : _M_context(__owner) { }

      service(const service&) = delete;
      service& operator=(const service&) = delete;

      virtual ~service() { } // TODO should not be inline

      // service observers:

      execution_context& context() const noexcept { return _M_context; }

    private:
      // service operations:

      virtual void shutdown() noexcept = 0;
      virtual void notify_fork(fork_event) { }

      friend class execution_context;
      execution_context& _M_context;
    };

    // construct / copy / destroy:

    execution_context() { }

    execution_context(const execution_context&) = delete;
    execution_context& operator=(const execution_context&) = delete;

    virtual ~execution_context()
    {
      shutdown();
      destroy();
    }

    // execution context operations:

    void
    notify_fork(fork_event __e)
    {
      auto __l = [=](auto& __svc) { __svc._M_ptr->notify_fork(__e); };
      if (__e == fork_event::prepare)
	std::for_each(_M_services.rbegin(), _M_services.rend(), __l);
      else
	std::for_each(_M_services.begin(), _M_services.end(), __l);
    }

  protected:
    // execution context protected operations:

    void
    shutdown()
    {
      std::for_each(_M_services.rbegin(), _M_services.rend(),
	  [=](auto& __svc) {
	    if (__svc._M_active)
	      {
	        __svc._M_ptr->shutdown();
		__svc._M_active = false;
	      }
	  });
    }

    void
    destroy()
    {
      while (_M_services.size())
	_M_services.pop_back();
      _M_keys.clear();
    }

  protected:

    template<typename _Service>
      static void
      _S_deleter(service* __svc) { delete static_cast<_Service*>(__svc); }

    struct _ServicePtr
    {
      template<typename _Service>
	explicit
	_ServicePtr(_Service* __svc)
	: _M_ptr(__svc, &_S_deleter<_Service>), _M_active(true) { }

      std::unique_ptr<service, void(*)(service*)> _M_ptr;
      bool _M_active;
    };

#if defined(_GLIBCXX_HAS_GTHREADS)
    using mutex_type = std::mutex;
#else
    struct mutex_type
    {
      void lock() const { }
      void unlock() const { }
    };
#endif
    mutable mutex_type _M_mutex;

    // Sorted in order of beginning of service object lifetime.
    std::list<_ServicePtr> _M_services;

    template<typename _Service, typename... _Args>
      service*
      _M_add_svc(_Args&&... __args)
      {
	_M_services.push_back(
	    _ServicePtr{new _Service{*this, std::forward<_Args>(__args)...}} );
	return _M_services.back()._M_ptr.get();
      }

    using __key_type = void(*)();

    template<typename _Key>
      static __key_type
      _S_key() { return reinterpret_cast<__key_type>(&_S_key<_Key>); }

    std::unordered_map<__key_type, service*> _M_keys;

    template<typename _Service>
      friend typename _Service::key_type&
      use_service(execution_context&);

    template<typename _Service, typename... _Args>
      friend _Service&
      make_service(execution_context&, _Args&&...);

    template<typename _Service>
      friend bool
      has_service(const execution_context&) noexcept;
  };

  // service access:

  template<typename _Service>
    typename _Service::key_type&
    use_service(execution_context& __ctx)
    {
      using _Key = typename _Service::key_type;
      static_assert(is_base_of<execution_context::service, _Key>::value,
	  "a service type must derive from execution_context::service");
      static_assert(is_base_of<_Key, _Service>::value,
	  "a service type must match or derive from its key_type");
      auto __key = execution_context::_S_key<_Key>();
      lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
      auto& __svc = __ctx._M_keys[__key];
      if (__svc == nullptr)
	{
	  __try {
	    __svc = __ctx._M_add_svc<_Service>();
	  } __catch(...) {
	    __ctx._M_keys.erase(__key);
	    __throw_exception_again;
	  }
	}
      return static_cast<_Key&>(*__svc);
    }

  template<typename _Service, typename... _Args>
    _Service&
    make_service(execution_context& __ctx, _Args&&... __args)
    {
      using _Key = typename _Service::key_type;
      static_assert(is_base_of<execution_context::service, _Key>::value,
	  "a service type must derive from execution_context::service");
      static_assert(is_base_of<_Key, _Service>::value,
	  "a service type must match or derive from its key_type");
      auto __key = execution_context::_S_key<_Key>();
      lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
      auto& __svc = __ctx._M_keys[__key];
      if (__svc != nullptr)
	throw service_already_exists();
      __try {
	__svc = __ctx._M_add_svc<_Service>(std::forward<_Args>(__args)...);
      } __catch(...) {
	__ctx._M_keys.erase(__key);
	__throw_exception_again;
      }
      return static_cast<_Service&>(*__svc);
    }

  template<typename _Service>
    inline bool
    has_service(const execution_context& __ctx) noexcept
    {
      using _Key = typename _Service::key_type;
      static_assert(is_base_of<execution_context::service, _Key>::value,
	  "a service type must derive from execution_context::service");
      static_assert(is_base_of<_Key, _Service>::value,
	  "a service type must match or derive from its key_type");
      lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
      return __ctx._M_keys.count(execution_context::_S_key<_Key>());
    }

  template<typename _Tp, typename = __void_t<>>
    struct __is_executor_impl : false_type
    { };

  // Check Executor requirements.
  template<typename _Tp, typename _Up = remove_const_t<_Tp>>
    auto
    __executor_reqs(_Up* __x = 0, const _Up* __cx = 0, void(*__f)() = 0,
		    const allocator<int>& __a = {})
    -> enable_if_t<__is_value_constructible<_Tp>::value, __void_t<
      decltype(*__cx == *__cx),
      decltype(*__cx != *__cx),
      decltype(__x->context()),
      decltype(__x->on_work_started()),
      decltype(__x->on_work_finished()),
      decltype(__x->dispatch(std::move(__f), __a)),
      decltype(__x->post(std::move(__f), __a)),
      decltype(__x->defer(std::move(__f), __a))
    >>;

  template<typename _Tp>
    struct __is_executor_impl<_Tp, decltype(__executor_reqs<_Tp>())>
    : true_type
    { };

  template<typename _Tp>
    struct is_executor : __is_executor_impl<_Tp>
    { };

  template<typename _Tp>
    constexpr bool is_executor_v = is_executor<_Tp>::value;

  template<typename _Tp, typename _Executor, typename = __void_t<>>
    struct __uses_executor_impl : false_type
    { };

  template<typename _Tp, typename _Executor>
    struct __uses_executor_impl<_Tp, _Executor,
				__void_t<typename _Tp::executor_type>>
    : is_convertible<_Executor, typename _Tp::executor_type>
    { };

  template<typename _Tp, typename _Executor>
    struct uses_executor : __uses_executor_impl<_Tp, _Executor>::type
    { };

  template<typename _Tp, typename _Executor>
    constexpr bool uses_executor_v = uses_executor<_Tp, _Executor>::value;

  template<typename _Tp, typename _Executor>
    class executor_binder
    {
      struct __use_exec { };

    public:
      // types:

      using target_type = _Tp;
      using executor_type = _Executor;

      // construct / copy / destroy:

      executor_binder(_Tp __t, const _Executor& __ex)
      : executor_binder(__use_exec{}, std::move(__t), __ex)
      { }

      executor_binder(const executor_binder&) = default;
      executor_binder(executor_binder&&) = default;

      template<typename _Up, typename _OtherExecutor>
	executor_binder(const executor_binder<_Up, _OtherExecutor>& __other)
	: executor_binder(__use_exec{}, __other.get(), __other.get_executor())
	{ }

      template<typename _Up, typename _OtherExecutor>
	executor_binder(executor_binder<_Up, _OtherExecutor>&& __other)
	: executor_binder(__use_exec{}, std::move(__other.get()),
			  __other.get_executor())
	{ }

      template<typename _Up, typename _OtherExecutor>
	executor_binder(executor_arg_t, const _Executor& __ex,
			const executor_binder<_Up, _OtherExecutor>& __other)
	: executor_binder(__use_exec{}, __other.get(), __ex)
	{ }

      template<typename _Up, typename _OtherExecutor>
	executor_binder(executor_arg_t, const _Executor& __ex,
			executor_binder<_Up, _OtherExecutor>&& __other)
	: executor_binder(__use_exec{}, std::move(__other.get()), __ex)
	{ }

      ~executor_binder();

      // executor binder access:

      _Tp& get() noexcept { return _M_target; }
      const _Tp& get() const noexcept { return _M_target; }
      executor_type get_executor() const noexcept { return _M_ex; }

      // executor binder invocation:

      template<class... _Args>
	result_of_t<_Tp&(_Args&&...)>
	operator()(_Args&&... __args)
	{ return std::__invoke(get(), std::forward<_Args>(__args)...); }

      template<class... _Args>
	result_of_t<const _Tp&(_Args&&...)>
	operator()(_Args&&... __args) const
	{ return std::__invoke(get(), std::forward<_Args>(__args)...); }

    private:
      template<typename _Up>
	using __use_exec_cond
	  = __and_<uses_executor<_Tp, _Executor>,
		   is_constructible<_Tp, executor_arg_t, _Executor, _Up>>;

      template<typename _Up, typename _Exec, typename =
	       enable_if_t<__use_exec_cond<_Up>::value>>
	executor_binder(__use_exec, _Up&& __u, _Exec&& __ex)
	: _M_ex(std::forward<_Exec>(__ex)),
	  _M_target(executor_arg, _M_ex, std::forward<_Up>(__u))
	{ }

      template<typename _Up, typename _Exec, typename =
	       enable_if_t<!__use_exec_cond<_Up>::value>>
	executor_binder(__use_exec, _Up&& __u, const _Exec& __ex)
	: _M_ex(std::forward<_Exec>(__ex)),
	  _M_target(std::forward<_Up>(__u))
	{ }

      _Executor	_M_ex;
      _Tp	_M_target;
    };

  template<typename _Tp, typename _Executor, typename _Signature>
    class async_result<executor_binder<_Tp, _Executor>, _Signature>
    {
      using __inner = async_result<_Tp, _Signature>;

    public:
      using completion_handler_type =
	executor_binder<typename __inner::completion_handler_type, _Executor>;

      using return_type = typename __inner::return_type;

      explicit
      async_result(completion_handler_type& __h)
      : _M_target(__h.get()) { }

      async_result(const async_result&) = delete;
      async_result& operator=(const async_result&) = delete;

      return_type get() { return _M_target.get(); }

    private:
      __inner _M_target;
    };

  template<typename _Tp, typename _Executor, typename _ProtoAlloc>
    struct associated_allocator<executor_binder<_Tp, _Executor>, _ProtoAlloc>
    {
      using type = associated_allocator_t<_Tp, _ProtoAlloc>;

      static type
      get(const executor_binder<_Tp, _Executor>& __b,
	  const _ProtoAlloc& __a = _ProtoAlloc()) noexcept
      { return associated_allocator<_Tp, _ProtoAlloc>::get(__b.get(), __a); }
    };

  template<typename _Tp, typename _Executor, typename _Executor1>
    struct associated_executor<executor_binder<_Tp, _Executor>, _Executor1>
    {
      using type = _Executor;

      static type
      get(const executor_binder<_Tp, _Executor>& __b,
	  const _Executor1& = _Executor1()) noexcept
      { return __b.get_executor(); }
    };

  template<typename _Executor>
    class executor_work_guard
    {
    public:
      // types:

      using executor_type = _Executor;

      // construct / copy / destroy:

      explicit
      executor_work_guard(const executor_type& __ex) noexcept
      : _M_ex(__ex), _M_owns(true)
      { _M_ex.on_work_started(); }

      executor_work_guard(const executor_work_guard& __other) noexcept
      : _M_ex(__other._M_ex), _M_owns(__other._M_owns)
      {
	if (_M_owns)
	  _M_ex.on_work_started();
      }

      executor_work_guard(executor_work_guard&& __other) noexcept
      : _M_ex(__other._M_ex), _M_owns(__other._M_owns)
      { __other._M_owns = false; }

      executor_work_guard& operator=(const executor_work_guard&) = delete;

      ~executor_work_guard()
      {
	if (_M_owns)
	  _M_ex.on_work_finished();
      }

      // executor work guard observers:

      executor_type get_executor() const noexcept { return _M_ex; }

      bool owns_work() const noexcept { return _M_owns; }

      // executor work guard modifiers:

      void reset() noexcept
      {
	if (_M_owns)
	  _M_ex.on_work_finished();
	_M_owns = false;
      }

    private:
      _Executor	_M_ex;
      bool	_M_owns;
    };


  class system_context : public execution_context
  {
  public:
    // types:

    using executor_type = system_executor;

    // construct / copy / destroy:

    system_context() = delete;
    system_context(const system_context&) = delete;
    system_context& operator=(const system_context&) = delete;

    ~system_context()
    {
      stop();
      join();
    }

    // system_context operations:

    executor_type get_executor() noexcept;

    void stop()
    {
      lock_guard<mutex_type> __lock(_M_mtx);
      _M_stopped = true;
      _M_cv.notify_all();
    }

    bool stopped() const noexcept
    {
      lock_guard<mutex_type> __lock(_M_mtx);
      return _M_stopped;
    }

    void join()
    {
      if (_M_thread.joinable())
	_M_thread.join();
    }

  private:
    friend system_executor;

    struct __tag { explicit __tag() = default; };
    system_context(__tag) { }

#ifndef _GLIBCXX_HAS_GTHREADS
    struct thread
    {
      bool joinable() const { return false; }
      void join() { }
    };
    struct condition_variable
    {
      void notify_all() { }
    };
#endif

    thread			_M_thread;
    mutable mutex_type		_M_mtx; // XXX can we reuse base's _M_mutex?
    condition_variable		_M_cv;
    queue<function<void()>>	_M_tasks;
    bool			_M_stopped = false;

#ifdef _GLIBCXX_HAS_GTHREADS
    void
    _M_run()
    {
      while (true)
	{
	  function<void()> __f;
	  {
	    unique_lock<mutex_type> __lock(_M_mtx);
	    _M_cv.wait(__lock,
		       [this]{ return _M_stopped || !_M_tasks.empty(); });
	    if (_M_stopped)
	      return;
	    __f = std::move(_M_tasks.front());
	    _M_tasks.pop();
	  }
	  __f();
	}
    }
#endif

    void
    _M_post(std::function<void()> __f __attribute__((__unused__)))
    {
      lock_guard<mutex_type> __lock(_M_mtx);
      if (_M_stopped)
	return;
#ifdef _GLIBCXX_HAS_GTHREADS
      if (!_M_thread.joinable())
	_M_thread = std::thread(&system_context::_M_run, this);
      _M_tasks.push(std::move(__f)); // XXX allocator not used
      _M_cv.notify_one();
#else
      __throw_system_error(EOPNOTSUPP);
#endif
    }

    static system_context&
    _S_get() noexcept
    {
      static system_context __sc(__tag{});
      return __sc;
    }
  };

  class system_executor
  {
  public:
    // executor operations:

    system_executor() { }

    system_context&
    context() const noexcept { return system_context::_S_get(); }

    void on_work_started() const noexcept { }
    void on_work_finished() const noexcept { }

    template<typename _Func, typename _ProtoAlloc>
      void
      dispatch(_Func&& __f, const _ProtoAlloc& __a) const
      { decay_t<_Func>{std::forward<_Func>(__f)}(); }

    template<typename _Func, typename _ProtoAlloc>
      void
      post(_Func&& __f, const _ProtoAlloc&) const // XXX allocator not used
      {
	system_context::_S_get()._M_post(std::forward<_Func>(__f));
      }

    template<typename _Func, typename _ProtoAlloc>
      void
      defer(_Func&& __f, const _ProtoAlloc& __a) const
      { post(std::forward<_Func>(__f), __a); }
  };

  inline system_executor
  system_context::get_executor() noexcept
  { return {}; }

  class bad_executor : public std::exception
  {
    virtual const char* what() const noexcept { return "bad executor"; }
  };

  inline void __throw_bad_executor() // TODO make non-inline
  {
#if __cpp_exceptions
    throw bad_executor();
#else
    __builtin_abort();
#endif
  }

  class executor
  {
  public:
    // construct / copy / destroy:

    executor() noexcept = default;

    executor(nullptr_t) noexcept { }
    executor(const executor&) noexcept = default;
    executor(executor&&) noexcept = default;

    template<typename _Executor>
      executor(_Executor __e)
      : _M_target(make_shared<_Tgt1<_Executor>>(std::move(__e)))
      { }

    template<typename _Executor, typename _ProtoAlloc>
      executor(allocator_arg_t, const _ProtoAlloc& __a, _Executor __e)
      : _M_target(allocate_shared<_Tgt2<_Executor, _ProtoAlloc>>(__a,
	    std::move(__e), __a))
      { }

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

    executor&
    operator=(nullptr_t) noexcept
    {
      _M_target = nullptr;
      return *this;
    }

    template<typename _Executor>
      executor&
      operator=(_Executor __e)
      {
	executor(std::move(__e)).swap(*this);
	return *this;
      }

    ~executor() = default;

    // executor modifiers:

    void
    swap(executor& __other) noexcept
    { _M_target.swap(__other._M_target); }

    template<typename _Executor, typename _Alloc>
      void
      assign(_Executor __e, const _Alloc& __a)
      { executor(allocator_arg, __a, std::move(__e)).swap(*this); }

    // executor operations:

    execution_context&
    context() const noexcept
    {
      __glibcxx_assert( _M_target );
      return _M_target->context();
    }

    void
    on_work_started() const noexcept
    {
      __glibcxx_assert( _M_target );
      return _M_target->on_work_started();
    }

    void
    on_work_finished() const noexcept
    {
      __glibcxx_assert( _M_target );
      return _M_target->on_work_finished();
    }

    template<typename _Func, typename _Alloc>
      void
      dispatch(_Func&& __f, const _Alloc& __a) const
      {
	if (!_M_target)
	  __throw_bad_executor();
	// _M_target->dispatch({allocator_arg, __a, std::forward<_Func>(__f)});
	_M_target->dispatch(std::forward<_Func>(__f));
      }

    template<typename _Func, typename _Alloc>
      void
      post(_Func&& __f, const _Alloc& __a) const
      {
	if (!_M_target)
	  __throw_bad_executor();
	// _M_target->post({allocator_arg, __a, std::forward<_Func>(__f)});
	_M_target->post(std::forward<_Func>(__f));
      }

    template<typename _Func, typename _Alloc>
      void
      defer(_Func&& __f, const _Alloc& __a) const
      {
	if (!_M_target)
	  __throw_bad_executor();
	// _M_target->defer({allocator_arg, __a, std::forward<_Func>(__f)});
	_M_target->defer(std::forward<_Func>(__f));
      }

    // executor capacity:

    explicit operator bool() const noexcept
    { return static_cast<bool>(_M_target); }

    // executor target access:

#if __cpp_rtti
    const type_info&
    target_type() const noexcept
    {
      if (_M_target)
	return *static_cast<const type_info*>(_M_target->target_type());
      return typeid(void);
    }
#endif

    template<typename _Executor>
      _Executor*
      target() noexcept
      {
	void* __p = nullptr;
	if (_M_target)
	  {
	    if (_M_target->_M_func == &_Tgt1<remove_cv_t<_Executor>>::_S_func)
	      __p = _M_target->_M_func(_M_target.get(), nullptr);
#if __cpp_rtti
	    else
	      __p = _M_target->target(&typeid(_Executor));
#endif
	  }
	return static_cast<_Executor*>(__p);
      }

    template<typename _Executor>
      const _Executor*
      target() const noexcept
      {
	const void* __p = nullptr;
	if (_M_target)
	  {
	    if (_M_target->_M_func == &_Tgt1<remove_cv_t<_Executor>>::_S_func)
	      return (_Executor*)_M_target->_M_func(_M_target.get(), nullptr);
#if __cpp_rtti
	    else
	      __p = _M_target->target(&typeid(_Executor));
#endif
	  }
	return static_cast<const _Executor*>(__p);
      }

  private:
    struct _Tgt
    {
      virtual void on_work_started() const noexcept = 0;
      virtual void on_work_finished() const noexcept = 0;
      virtual execution_context& context() const noexcept = 0;
      virtual void dispatch(std::function<void()>) const = 0;
      virtual void post(std::function<void()>) const = 0;
      virtual void defer(std::function<void()>) const = 0;
      virtual const void* target_type() const noexcept = 0;
      virtual void* target(const void*) noexcept = 0;
      virtual bool _M_equals(_Tgt*) const noexcept = 0;

      using _Func = void* (_Tgt*, const _Tgt*);
      _Func* _M_func; // Provides access to target without RTTI
    };

    template<typename _Ex>
      struct _Tgt1 : _Tgt
      {
	explicit
	_Tgt1(_Ex&& __ex)
	: _M_ex(std::move(__ex))
	{ this->_M_func = &_S_func; }

	void
	on_work_started() const noexcept override
	{ _M_ex.on_work_started(); }

	void
	on_work_finished() const noexcept override
	{ _M_ex.on_work_finished(); }

	execution_context&
	context() const noexcept override
	{ return _M_ex.context(); }

	void
	dispatch(std::function<void()> __f) const override
	{ _M_ex.dispatch(std::move(__f), allocator<void>()); }

	void
	post(std::function<void()> __f) const override
	{ _M_ex.post(std::move(__f), allocator<void>()); }

	void
	defer(std::function<void()> __f) const override
	{ _M_ex.defer(std::move(__f), allocator<void>()); }

	const void*
	target_type() const noexcept override
	{
#if __cpp_rtti
	  return &typeid(_Ex);
#else
	  return nullptr;
#endif
	}

	void*
	target(const void* __ti) noexcept override
	{
#if __cpp_rtti
	  if (*static_cast<const type_info*>(__ti) == typeid(_Ex))
	    return std::__addressof(_M_ex);
#endif
	  return nullptr;
	}

	bool
	_M_equals(_Tgt* __tgt) const noexcept override
	{
#if __cpp_rtti
	  if (const void* __p = __tgt->target(&typeid(_Ex)))
	    return *static_cast<const _Ex*>(__p) == _M_ex;
#endif
	  return false;
	}

	_Ex _M_ex [[__no_unique_address__]];

	static void*
	_S_func(_Tgt* __p, const _Tgt* __q) noexcept
	{
	  auto& __ex = static_cast<_Tgt1*>(__p)->_M_ex;
	  if (__q)
	    {
	      if (__ex == static_cast<const _Tgt1*>(__q)->_M_ex)
		return __p;
	      else
		return nullptr;
	    }
	  else
	    return std::__addressof(__ex);
	}
      };

    template<typename _Ex, typename _Alloc>
      struct _Tgt2 : _Tgt1<_Ex>
      {
	explicit
	_Tgt2(_Ex&& __ex, const _Alloc& __a)
	: _Tgt1<_Ex>(std::move(__ex)), _M_alloc(__a) { }

	void
	dispatch(std::function<void()> __f) const override
	{ this->_M_ex.dispatch(std::move(__f), _M_alloc); }

	void
	post(std::function<void()> __f) const override
	{ this->_M_ex.post(std::move(__f), _M_alloc); }

	void
	defer(std::function<void()> __f) const override
	{ this->_M_ex.defer(std::move(__f), _M_alloc); }

	_Alloc _M_alloc [[__no_unique_address__]];
      };

    // Partial specialization for std::allocator<T>.
    // Don't store the allocator.
    template<typename _Ex, typename _Tp>
      struct _Tgt2<_Ex, std::allocator<_Tp>> : _Tgt1<_Ex>
      { };

    friend bool
    operator==(const executor& __a, const executor& __b) noexcept
    {
      _Tgt* __ta = __a._M_target.get();
      _Tgt* __tb = __b._M_target.get();
      if (__ta == __tb)
	return true;
      if (!__ta || !__tb)
	return false;
      if (__ta->_M_func == __tb->_M_func)
	return __ta->_M_func(__ta, __tb);
      return __ta->_M_equals(__tb);
    }

    shared_ptr<_Tgt> _M_target;
  };

  template<> struct is_executor<executor> : true_type { };

  /// executor comparisons
  inline bool
  operator==(const executor& __e, nullptr_t) noexcept
  { return !__e; }

  inline bool
  operator==(nullptr_t, const executor& __e) noexcept
  { return !__e; }

  inline bool
  operator!=(const executor& __a, const executor& __b) noexcept
  { return !(__a == __b); }

  inline bool
  operator!=(const executor& __e, nullptr_t) noexcept
  { return (bool)__e; }

  inline bool
  operator!=(nullptr_t, const executor& __e) noexcept
  { return (bool)__e; }

  /// Swap two executor objects.
  inline void swap(executor& __a, executor& __b) noexcept { __a.swap(__b); }


  template<typename _CompletionHandler>
    struct __dispatcher
    {
      explicit
      __dispatcher(_CompletionHandler& __h)
      : _M_h(std::move(__h)), _M_w(net::make_work_guard(_M_h))
      { }

      void operator()()
      {
	auto __alloc = net::get_associated_allocator(_M_h);
	_M_w.get_executor().dispatch(std::move(_M_h), __alloc);
	_M_w.reset();
      }

      _CompletionHandler _M_h;
      decltype(net::make_work_guard(_M_h)) _M_w;
    };

  template<typename _CompletionHandler>
    inline __dispatcher<_CompletionHandler>
    __make_dispatcher(_CompletionHandler& __h)
    { return __dispatcher<_CompletionHandler>{__h}; }



  // dispatch:

  template<typename _CompletionToken>
    inline __deduced_t<_CompletionToken, void()>
    dispatch(_CompletionToken&& __token)
    {
      async_completion<_CompletionToken, void()> __cmpl{__token};
      auto __ex = net::get_associated_executor(__cmpl.completion_handler);
      auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
      __ex.dispatch(std::move(__cmpl.completion_handler), __alloc);
      return __cmpl.result.get();
    }

  template<typename _Executor, typename _CompletionToken>
    inline
    enable_if_t<is_executor<_Executor>::value,
		__deduced_t<_CompletionToken, void()>>
    dispatch(const _Executor& __ex, _CompletionToken&& __token)
    {
      async_completion<_CompletionToken, void()> __cmpl{__token};
      auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
      __ex.dispatch(net::__make_dispatcher(__cmpl.completion_handler),
		    __alloc);
      return __cmpl.result.get();
    }

  template<typename _ExecutionContext, typename _CompletionToken>
    inline
    enable_if_t<__is_exec_context<_ExecutionContext>::value,
		__deduced_t<_CompletionToken, void()>>
    dispatch(_ExecutionContext& __ctx, _CompletionToken&& __token)
    {
      return net::dispatch(__ctx.get_executor(),
			   forward<_CompletionToken>(__token));
    }

  // post:

  template<typename _CompletionToken>
    inline __deduced_t<_CompletionToken, void()>
    post(_CompletionToken&& __token)
    {
      async_completion<_CompletionToken, void()> __cmpl{__token};
      auto __ex = net::get_associated_executor(__cmpl.completion_handler);
      auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
      __ex.post(std::move(__cmpl.completion_handler), __alloc);
      return __cmpl.result.get();
    }

  template<typename _Executor, typename _CompletionToken>
    inline
    enable_if_t<is_executor<_Executor>::value,
		__deduced_t<_CompletionToken, void()>>
    post(const _Executor& __ex, _CompletionToken&& __token)
    {
      async_completion<_CompletionToken, void()> __cmpl{__token};
      auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
      __ex.post(net::__make_dispatcher(__cmpl.completion_handler), __alloc);
      return __cmpl.result.get();
    }

  template<typename _ExecutionContext, typename _CompletionToken>
    inline
    enable_if_t<__is_exec_context<_ExecutionContext>::value,
		__deduced_t<_CompletionToken, void()>>
    post(_ExecutionContext& __ctx, _CompletionToken&& __token)
    {
      return net::post(__ctx.get_executor(),
		       forward<_CompletionToken>(__token));
    }

  // defer:

  template<typename _CompletionToken>
    inline __deduced_t<_CompletionToken, void()>
    defer(_CompletionToken&& __token)
    {
      async_completion<_CompletionToken, void()> __cmpl{__token};
      auto __ex = net::get_associated_executor(__cmpl.completion_handler);
      auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
      __ex.defer(std::move(__cmpl.completion_handler), __alloc);
      return __cmpl.result.get();
    }

  template<typename _Executor, typename _CompletionToken>
    inline
    enable_if_t<is_executor<_Executor>::value,
		__deduced_t<_CompletionToken, void()>>
    defer(const _Executor& __ex, _CompletionToken&& __token)
    {
      async_completion<_CompletionToken, void()> __cmpl{__token};
      auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
      __ex.defer(net::__make_dispatcher(__cmpl.completion_handler), __alloc);
      return __cmpl.result.get();
    }

  template<typename _ExecutionContext, typename _CompletionToken>
    inline
    enable_if_t<__is_exec_context<_ExecutionContext>::value,
		__deduced_t<_CompletionToken, void()>>
    defer(_ExecutionContext& __ctx, _CompletionToken&& __token)
    {
      return net::defer(__ctx.get_executor(),
			forward<_CompletionToken>(__token));
    }


  template<typename _Executor>
    class strand
    {
    public:
      // types:

      using inner_executor_type = _Executor;

      // construct / copy / destroy:

      strand(); // TODO make state

      explicit strand(_Executor __ex) : _M_inner_ex(__ex) { } // TODO make state

      template<typename _Alloc>
	strand(allocator_arg_t, const _Alloc& __a, _Executor __ex)
	: _M_inner_ex(__ex) { } // TODO make state

      strand(const strand& __other) noexcept
      : _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }

      strand(strand&& __other) noexcept
      : _M_state(std::move(__other._M_state)),
	_M_inner_ex(std::move(__other._M_inner_ex)) { }

      template<typename _OtherExecutor>
	strand(const strand<_OtherExecutor>& __other) noexcept
	: _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }

      template<typename _OtherExecutor>
	strand(strand<_OtherExecutor>&& __other) noexcept
	: _M_state(std::move(__other._M_state)),
	  _M_inner_ex(std::move(__other._M_inner_ex)) { }

      strand&
      operator=(const strand& __other) noexcept
      {
	static_assert(is_copy_assignable<_Executor>::value,
		      "inner executor type must be CopyAssignable");

	// TODO lock __other
	// TODO copy state
	_M_inner_ex = __other._M_inner_ex;
	return *this;
      }

      strand&
      operator=(strand&& __other) noexcept
      {
	static_assert(is_move_assignable<_Executor>::value,
		      "inner executor type must be MoveAssignable");

	// TODO move state
	_M_inner_ex = std::move(__other._M_inner_ex);
	return *this;
      }

      template<typename _OtherExecutor>
	strand&
	operator=(const strand<_OtherExecutor>& __other) noexcept
	{
	  static_assert(is_convertible<_OtherExecutor, _Executor>::value,
			"inner executor type must be compatible");

	  // TODO lock __other
	  // TODO copy state
	  _M_inner_ex = __other._M_inner_ex;
	  return *this;
	}

      template<typename _OtherExecutor>
	strand&
	operator=(strand<_OtherExecutor>&& __other) noexcept
	{
	  static_assert(is_convertible<_OtherExecutor, _Executor>::value,
			"inner executor type must be compatible");

	  // TODO move state
	  _M_inner_ex = std::move(__other._M_inner_ex);
	  return *this;
	}

      ~strand()
      {
	// the task queue outlives this object if non-empty
	// TODO create circular ref in queue?
      }

      // strand operations:

      inner_executor_type
      get_inner_executor() const noexcept
      { return _M_inner_ex; }

      bool
      running_in_this_thread() const noexcept
      { return _M_state->running_in_this_thread(); }

      execution_context&
      context() const noexcept
      { return _M_inner_ex.context(); }

      void on_work_started() const noexcept { _M_inner_ex.on_work_started(); }
      void on_work_finished() const noexcept { _M_inner_ex.on_work_finished(); }

      template<typename _Func, typename _Alloc>
	void
	dispatch(_Func&& __f, const _Alloc& __a) const
	{
	  if (running_in_this_thread())
	    decay_t<_Func>{std::forward<_Func>(__f)}();
	  else
	    post(std::forward<_Func>(__f), __a);
	}

      template<typename _Func, typename _Alloc>
	void
	post(_Func&& __f, const _Alloc& __a) const; // TODO

      template<typename _Func, typename _Alloc>
	void
	defer(_Func&& __f, const _Alloc& __a) const
	{ post(std::forward<_Func>(__f), __a); }

    private:
      friend bool
      operator==(const strand& __a, const strand& __b)
      { return __a._M_state == __b._M_state; }

      // TODO add synchronised queue
      struct _State
      {
#if defined(_GLIBCXX_HAS_GTHREADS)
	bool
	running_in_this_thread() const noexcept
	{ return std::this_thread::get_id() == _M_running_on; }

	std::thread::id _M_running_on;
#else
	bool running_in_this_thread() const { return true; }
#endif
      };
      shared_ptr<_State> _M_state;
      _Executor _M_inner_ex;
    };

#if defined(_GLIBCXX_HAS_GTHREADS)

  // Completion token for asynchronous operations initiated with use_future.
  template<typename _Func, typename _Alloc>
    struct __use_future_ct
    {
      std::tuple<_Func, _Alloc> _M_t;
    };

  template<typename _Func, typename _Tp>
    struct __use_future_ct<_Func, std::allocator<_Tp>>
    {
      _Func _M_f;
    };

  template<typename _ProtoAllocator = allocator<void>>
    class use_future_t
    {
    public:
      // use_future_t types:
      using allocator_type = _ProtoAllocator;

      // use_future_t members:
      constexpr
      use_future_t()
      noexcept(is_nothrow_default_constructible<_ProtoAllocator>::value)
      : _M_alloc() { }

      explicit
      use_future_t(const _ProtoAllocator& __a) noexcept : _M_alloc(__a) { }

      template<typename _OtherAllocator>
	use_future_t<_OtherAllocator>
	rebind(const _OtherAllocator& __a) const noexcept
	{ return use_future_t<_OtherAllocator>(__a); }

      allocator_type get_allocator() const noexcept { return _M_alloc; }

      template<typename _Func>
	auto
	operator()(_Func&& __f) const
	{
	  using _Token = __use_future_ct<decay_t<_Func>, _ProtoAllocator>;
	  return _Token{ {std::forward<_Func>(__f), _M_alloc} };
	}

    private:
      _ProtoAllocator _M_alloc;
    };

  template<typename _Tp>
    class use_future_t<std::allocator<_Tp>>
    {
    public:
      // use_future_t types:
      using allocator_type = std::allocator<_Tp>;

      // use_future_t members:
      constexpr use_future_t() noexcept = default;

      explicit
      use_future_t(const allocator_type& __a) noexcept { }

      template<class _Up>
	use_future_t<std::allocator<_Up>>
	rebind(const std::allocator<_Up>& __a) const noexcept
	{ return use_future_t<std::allocator<_Up>>(__a); }

      allocator_type get_allocator() const noexcept { return {}; }

      template<typename _Func>
	auto
	operator()(_Func&& __f) const
	{
	  using _Token = __use_future_ct<decay_t<_Func>, allocator_type>;
	  return _Token{std::forward<_Func>(__f)};
	}
    };

  constexpr use_future_t<> use_future = use_future_t<>();

  template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
    class async_result<__use_future_ct<_Func, _Alloc>, _Res(_Args...)>;

  template<typename _Result, typename _Executor>
    struct __use_future_ex;

  // Completion handler for asynchronous operations initiated with use_future.
  template<typename _Func, typename... _Args>
    struct __use_future_ch
    {
      template<typename _Alloc>
	explicit
	__use_future_ch(__use_future_ct<_Func, _Alloc>&& __token)
	: _M_f{ std::move(std::get<0>(__token._M_t)) },
	  _M_promise{ std::get<1>(__token._M_t) }
	{ }

      template<typename _Tp>
	explicit
	__use_future_ch(__use_future_ct<_Func, std::allocator<_Tp>>&& __token)
	: _M_f{ std::move(__token._M_f) }
	{ }

      void
      operator()(_Args&&... __args)
      {
	__try
	  {
	    _M_promise.set_value(_M_f(std::forward<_Args>(__args)...));
	  }
	__catch(__cxxabiv1::__forced_unwind&)
	  {
	    __throw_exception_again;
	  }
	__catch(...)
	  {
	    _M_promise.set_exception(std::current_exception());
	  }
      }

      using __result = result_of_t<_Func(decay_t<_Args>...)>;

      future<__result> get_future() { return _M_promise.get_future(); }

    private:
      template<typename _Result, typename _Executor>
	friend struct __use_future_ex;

      _Func _M_f;
      mutable promise<__result> _M_promise;
    };

  // Specialization of async_result for operations initiated with use_future.
  template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
    class async_result<__use_future_ct<_Func, _Alloc>, _Res(_Args...)>
    {
    public:
      using completion_handler_type = __use_future_ch<_Func, _Args...>;
      using return_type = future<typename completion_handler_type::__result>;

      explicit
      async_result(completion_handler_type& __h)
      : _M_future(__h.get_future())
      { }

      async_result(const async_result&) = delete;
      async_result& operator=(const async_result&) = delete;

      return_type get() { return std::move(_M_future); }

    private:
      return_type _M_future;
    };

  template<typename _Result, typename _Executor>
    struct __use_future_ex
    {
      template<typename _Handler>
      __use_future_ex(const _Handler& __h, _Executor __ex)
      : _M_t(__h._M_promise, __ex)
      { }

      template<typename _Fn, typename _Alloc>
	void
	dispatch(_Fn&& __fn)
	{
	  __try
	    {
	      std::get<1>(_M_t).dispatch(std::forward<_Fn>(__fn));
	    }
	  __catch(__cxxabiv1::__forced_unwind&)
	    {
	      __throw_exception_again;
	    }
	  __catch(...)
	    {
	      std::get<0>(_M_t).set_exception(std::current_exception());
	    }
	}

      template<typename _Fn, typename _Alloc>
	void
	post(_Fn&& __fn)
	{
	  __try
	    {
	      std::get<1>(_M_t).post(std::forward<_Fn>(__fn));
	    }
	  __catch(__cxxabiv1::__forced_unwind&)
	    {
	      __throw_exception_again;
	    }
	  __catch(...)
	    {
	      std::get<0>(_M_t).set_exception(std::current_exception());
	    }
	}

      template<typename _Fn, typename _Alloc>
	void
	defer(_Fn&& __fn)
	{
	  __try
	    {
	      std::get<1>(_M_t).defer(std::forward<_Fn>(__fn));
	    }
	  __catch(__cxxabiv1::__forced_unwind&)
	    {
	      __throw_exception_again;
	    }
	  __catch(...)
	    {
	      std::get<0>(_M_t).set_exception(std::current_exception());
	    }
	}

    private:
      tuple<promise<_Result>&, _Executor> _M_t;
    };

  template<typename _Func, typename... _Args, typename _Executor>
    struct associated_executor<__use_future_ch<_Func, _Args...>, _Executor>
    {
    private:
      using __handler = __use_future_ch<_Func, _Args...>;

      using type = __use_future_ex<typename __handler::__result, _Executor>;

      static type
      get(const __handler& __h, const _Executor& __ex)
      { return { __h, __ex }; }
    };

#if 0

  // [async.use.future.traits]
  template<typename _Allocator, typename _Ret, typename... _Args>
    class handler_type<use_future_t<_Allocator>, _Ret(_Args...)> // TODO uglify name
    {
      template<typename... _Args>
	struct __is_error_result : false_type { };

      template<typename... _Args>
	struct __is_error_result<error_code, _Args...> : true_type { };

      template<typename... _Args>
	struct __is_error_result<exception_ptr, _Args...> : true_type { };

      static exception_ptr
      _S_exptr(exception_ptr& __ex)
      { return std::move(__ex); }

      static exception_ptr
      _S_exptr(const error_code& __ec)
      { return make_exception_ptr(system_error(__ec)); }

      template<bool _IsError, typename... _UArgs>
	struct _Type;

      // N == 0
      template<bool _IsError>
	struct _Type<_IsError>
	{
	  std::promise<void> _M_promise;

	  void
	  operator()()
	  {
	    _M_promise.set_value();
	  }
	};

      // N == 1, U0 is error_code or exception_ptr
      template<typename _UArg0>
	struct _Type<true, _UArg0>
	{
	  std::promise<void> _M_promise;

	  template<typename _Arg0>
	    void
	    operator()(_Arg0&& __a0)
	    {
	      if (__a0)
		_M_promise.set_exception(_S_exptr(__a0));
	      else
		_M_promise.set_value();
	    }
	};

      // N == 1, U0 is not error_code or exception_ptr
      template<typename _UArg0>
	struct _Type<false, _UArg0>
	{
	  std::promise<_UArg0> _M_promise;

	  template<typename _Arg0>
	    void
	    operator()(_Arg0&& __a0)
	    {
	      _M_promise.set_value(std::forward<_Arg0>(__a0));
	    }
	};

      // N == 2, U0 is error_code or exception_ptr
      template<typename _UArg0, typename _UArg1>
	struct _Type<true, _UArg0, _UArg1>
	{
	  std::promise<_UArg1> _M_promise;

	  template<typename _Arg0, typename _Arg1>
	    void
	    operator()(_Arg0&& __a0, _Arg1&& __a1)
	    {
	      if (__a0)
		_M_promise.set_exception(_S_exptr(__a0));
	      else
		_M_promise.set_value(std::forward<_Arg1>(__a1));
	    }
	};

      // N >= 2, U0 is not error_code or exception_ptr
      template<typename... _UArgs>
	struct _Type<false, _UArgs...>
	{
	  static_assert(sizeof...(_UArgs) > 1, "wrong partial specialization");

	  std::promise<tuple<_UArgs...>> _M_promise;

	  template<typename... _Args>
	    void
	    operator()(_Args&&... __args)
	    {
	      _M_promise.set_value(
		  std::forward_as_tuple(std::forward<_Args>(__args)...));
	    }
	};

      // N > 2, U0 is error_code or exception_ptr
      template<typename _UArg0, typename... _UArgs>
	struct _Type<true, _UArg0, _UArgs...>
	{
	  static_assert(sizeof...(_UArgs) > 1, "wrong partial specialization");

	  std::promise<tuple<_UArgs...>> _M_promise;

	  template<typename _Arg0, typename... _Args>
	    void
	    operator()(_Arg0&& __a0, _Args&&... __args)
	    {
	      if (__a0)
		_M_promise.set_exception(_S_exptr(__a0));
	      else
		_M_promise.set_value(
		    std::forward_as_tuple(std::forward<_Args>(__args)...));
	    }
	};

    public:
      using type =
	_Type<__is_error_result<_Args...>::value, decay_t<_Args>...>;
    };


  template<typename _Alloc, typename _Ret, typename... _Args>
    struct async_result<use_future_t<_Alloc>, _Ret(_Args...)>
    {
      using completion_handler_type
	= typename handler_type<use_future_t<_Alloc>, _Ret(_Args...)>::type;

      using return_type = void; // XXX TODO ???;

      explicit
      async_result(completion_handler_type& __h) : _M_handler(__h) { }

      auto get() { return _M_handler._M_provider.get_future(); }

      async_result(const async_result&) = delete;
      async_result& operator=(const async_result&) = delete;

      return_type get() { return _M_handler._M_promise.get_future(); }

    private:
      completion_handler_type& _M_handler;
    };

  // TODO specialize associated_executor for
  // async_result<use_future_t<A>, Sig>::completion_handler_type
  // to use a __use_future_ex
  // (probably need to move _Type outside of handler_type so we don't have
  // a non-deduced context)

#endif

  // [async.packaged.task.specializations]
  template<typename _Ret, typename... _Args, typename _Signature>
    class async_result<packaged_task<_Ret(_Args...)>, _Signature>
    {
    public:
      using completion_handler_type = packaged_task<_Ret(_Args...)>;
      using return_type = future<_Ret>;

      explicit
      async_result(completion_handler_type& __h)
      : _M_future(__h.get_future()) { }

      async_result(const async_result&) = delete;
      async_result& operator=(const async_result&) = delete;

      return_type get() { return std::move(_M_future); }

    private:
      return_type _M_future;
    };

#endif // _GLIBCXX_HAS_GTHREADS

  /// @}

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

  template<typename _Alloc>
    struct uses_allocator<experimental::net::executor, _Alloc>
    : true_type {};

_GLIBCXX_END_NAMESPACE_VERSION
} // namespace std

#endif // C++14

#endif // _GLIBCXX_EXPERIMENTAL_EXECUTOR
