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

// Copyright (C) 2015-2019 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.
 */

#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 <utility>
#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
{

  /**
   * @ingroup networking
   * @{
   */

  /// 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 { };

  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& __a, const executor& __b) noexcept;

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

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

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

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

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

  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:
      typedef _CompletionToken completion_handler_type;
      typedef void return_type;

      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;
    };

    mutable std::mutex _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>();
      std::lock_guard<std::mutex> __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>();
      std::lock_guard<std::mutex> __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");
      std::lock_guard<std::mutex> __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:

      typedef _Tp target_type;
      typedef _Executor executor_type;

      // 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>
    {
      typedef associated_allocator_t<_Tp, _ProtoAlloc> type;

      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>
    {
      typedef _Executor type;

      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:

      typedef _Executor executor_type;

      // 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:

    typedef system_executor executor_type;

    // construct / copy / destroy:

    system_context() = default;
    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> __lock(_M_mtx);
      _M_stopped = true;
      _M_cv.notify_all();
    }

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

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

  private:
    friend system_executor;

    struct __tag { };
    system_context(__tag) { }

    thread			_M_thread;
    mutable mutex		_M_mtx;
    condition_variable		_M_cv;
    queue<function<void()>>	_M_tasks;
    bool			_M_stopped = false;

    void
    _M_run()
    {
      while (true)
	{
	  function<void()> __f;
	  {
	    unique_lock<mutex> __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();
	}
    }

    void
    _M_post(std::function<void()> __f)
    {
      lock_guard<mutex> __lock(_M_mtx);
      if (_M_stopped)
	return;
      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();
    }

    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(_M_create(std::move(__e)))
      { }

    template<typename _Executor, typename _ProtoAlloc>
      executor(allocator_arg_t, const _ProtoAlloc& __a, _Executor __e)
      : _M_target(_M_create(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
    { return _M_target ? _M_target->target_type() : typeid(void); }

    template<typename _Executor>
      _Executor*
      target() noexcept
      {
	if (_M_target)
	  if (const auto* __p = _M_target->target(typeid(_Executor)))
	    return const_cast<_Executor*>(static_cast<const _Executor>(__p));
	return nullptr;
      }

    template<typename _Executor>
      const _Executor*
      target() const noexcept
      {
	if (_M_target)
	  if (const auto* __p = _M_target->target(typeid(_Executor)))
	    return static_cast<const _Executor*>(__p);
	return nullptr;
      }
#endif

  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;
#if __cpp_rtti
      virtual const type_info& target_type() const = 0;
      virtual void* target(const std::type_info&) const = 0;
      virtual bool _M_equals(_Tgt*) const noexcept = 0;
      virtual const void* _M_get_executor() const noexcept = 0;
#endif
    };

    template<typename _Ex, typename _Alloc>
      struct _TgtImpl : _Tgt
      {
	explicit
	_TgtImpl(_Ex&& __ex, const _Alloc& __a)
	: _M_impl(std::move(__ex), __a) { }

	void on_work_started() const noexcept { _M_ex().on_work_started(); }
	void on_work_finished() const noexcept { _M_ex().on_work_finished(); }
	execution_context& context() const noexcept { return _M_ex().context(); }
	void
	dispatch(std::function<void()> __f) const
	{ _M_ex().dispatch(std::move(__f), _M_alloc()); }
	void
	post(std::function<void()> __f) const
	{ _M_ex().post(std::move(__f), _M_alloc()); }
	void
	defer(std::function<void()> __f) const
	{ _M_ex().defer(std::move(__f), _M_alloc()); }

#if __cpp_rtti
	virtual const type_info&
	target_type() const
	{ return typeid(_Ex); }

	virtual const void*
	target(const std::type_info& __ti) const
	{
	  if (__ti == typeid(_Ex))
	    return std::addressof(_M_ex());
	  return nullptr;
	}

	virtual bool
	_M_equals(const _Tgt* __tgt) const noexcept
	{
	  if (__tgt->target_type() == typeid(_Ex))
	    *static_cast<const _Ex*>(__tgt->_M_get_executor()) == _M_ex();
	  return false;
	}

	virtual const void*
	_M_get_executor() const noexcept
	{ return std::addressof(_M_ex()); }
#endif

	_Ex& _M_ex() { return std::get<0>(_M_impl); }
	_Alloc& _M_alloc() { return std::get<1>(_M_impl); }
	std::tuple<_Ex, _Alloc> _M_impl;
      };

    template<typename _Ex, typename _Alloc = std::allocator<void>>
      shared_ptr<_Tgt>
      _M_create(_Ex&& __ex, const _Alloc& __a = _Alloc())
      {
	return allocate_shared<_TgtImpl<_Ex, _Alloc>>(__a, std::move(__ex),
						      __a);
      }

    friend bool
    operator==(const executor& __a, const executor& __b) noexcept
    {
      if (__a._M_target == __b._M_target)
	return true;
      if (!__a._M_target || !__b._M_target)
	return false;
#if __cpp_rtti
      return __a._M_target->_M_equals(__b._M_target.get());
#else
      return false; // XXX can we do better?
#endif
    }

    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; }

  /// 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:

      typedef _Executor inner_executor_type;

      // 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 std::this_thread::get_id() == _M_state->_M_running_on; }

      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
      {
	std::thread::id _M_running_on;
      };
      shared_ptr<_State> _M_state;
      _Executor _M_inner_ex;
    };

#if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)

  // 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 _ProtoAllocator = allocator<void>>
    class use_future_t
    {
    public:
      // use_future_t types:
      typedef _ProtoAllocator allocator_type;

      // use_future_t members:
      constexpr use_future_t() noexcept : _M_alloc() { }

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

      template<class _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;
    };

  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) }
	{ }

      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

  /// @}

} // 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
