Home | History | Annotate | Line # | Download | only in experimental
      1 // <experimental/executor> -*- C++ -*-
      2 
      3 // Copyright (C) 2015-2022 Free Software Foundation, Inc.
      4 //
      5 // This file is part of the GNU ISO C++ Library.  This library is free
      6 // software; you can redistribute it and/or modify it under the
      7 // terms of the GNU General Public License as published by the
      8 // Free Software Foundation; either version 3, or (at your option)
      9 // any later version.
     10 
     11 // This library is distributed in the hope that it will be useful,
     12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 // GNU General Public License for more details.
     15 
     16 // Under Section 7 of GPL version 3, you are granted additional
     17 // permissions described in the GCC Runtime Library Exception, version
     18 // 3.1, as published by the Free Software Foundation.
     19 
     20 // You should have received a copy of the GNU General Public License and
     21 // a copy of the GCC Runtime Library Exception along with this program;
     22 // see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 // <http://www.gnu.org/licenses/>.
     24 
     25 /** @file experimental/executor
     26  *  This is a TS C++ Library header.
     27  *  @ingroup networking-ts
     28  */
     29 
     30 #ifndef _GLIBCXX_EXPERIMENTAL_EXECUTOR
     31 #define _GLIBCXX_EXPERIMENTAL_EXECUTOR 1
     32 
     33 #pragma GCC system_header
     34 
     35 #if __cplusplus >= 201402L
     36 
     37 #include <algorithm>
     38 #include <condition_variable>
     39 #include <functional>
     40 #include <future>
     41 #include <list>
     42 #include <queue>
     43 #include <thread>
     44 #include <tuple>
     45 #include <unordered_map>
     46 #include <experimental/netfwd>
     47 #include <bits/unique_ptr.h>
     48 #include <experimental/bits/net.h>
     49 
     50 namespace std _GLIBCXX_VISIBILITY(default)
     51 {
     52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
     53 namespace experimental
     54 {
     55 namespace net
     56 {
     57 inline namespace v1
     58 {
     59 
     60   /** @addtogroup networking-ts
     61    *  @{
     62    */
     63 
     64   /// Customization point for asynchronous operations.
     65   template<typename _CompletionToken, typename _Signature, typename = void>
     66     class async_result;
     67 
     68   /// Convenience utility to help implement asynchronous operations.
     69   template<typename _CompletionToken, typename _Signature>
     70     class async_completion;
     71 
     72   template<typename _Tp, typename _ProtoAlloc, typename = __void_t<>>
     73     struct __associated_allocator_impl
     74     {
     75       using type = _ProtoAlloc;
     76 
     77       static type
     78       _S_get(const _Tp&, const _ProtoAlloc& __a) noexcept { return __a; }
     79     };
     80 
     81   template<typename _Tp, typename _ProtoAlloc>
     82     struct __associated_allocator_impl<_Tp, _ProtoAlloc,
     83 				       __void_t<typename _Tp::allocator_type>>
     84     {
     85       using type = typename _Tp::allocator_type;
     86 
     87       static type
     88       _S_get(const _Tp& __t, const _ProtoAlloc&) noexcept
     89       { return __t.get_allocator(); }
     90     };
     91 
     92   /// Helper to associate an allocator with a type.
     93   template<typename _Tp, typename _ProtoAllocator = allocator<void>>
     94     struct associated_allocator
     95     : __associated_allocator_impl<_Tp, _ProtoAllocator>
     96     {
     97       static auto
     98       get(const _Tp& __t,
     99 	  const _ProtoAllocator& __a = _ProtoAllocator()) noexcept
    100       {
    101 	using _Impl = __associated_allocator_impl<_Tp, _ProtoAllocator>;
    102 	return _Impl::_S_get(__t, __a);
    103       }
    104     };
    105 
    106   /// Alias template for associated_allocator.
    107   template<typename _Tp, typename _ProtoAllocator = allocator<void>>
    108     using associated_allocator_t
    109       = typename associated_allocator<_Tp, _ProtoAllocator>::type;
    110 
    111   // get_associated_allocator:
    112 
    113   template<typename _Tp>
    114     inline associated_allocator_t<_Tp>
    115     get_associated_allocator(const _Tp& __t) noexcept
    116     { return associated_allocator<_Tp>::get(__t); }
    117 
    118   template<typename _Tp, typename _ProtoAllocator>
    119     inline associated_allocator_t<_Tp, _ProtoAllocator>
    120     get_associated_allocator(const _Tp& __t,
    121 			     const _ProtoAllocator& __a) noexcept
    122     { return associated_allocator<_Tp, _ProtoAllocator>::get(__t, __a); }
    123 
    124   enum class fork_event { prepare, parent, child };
    125 
    126   /// An extensible, type-safe, polymorphic set of services.
    127   class execution_context;
    128 
    129   class service_already_exists : public logic_error
    130   {
    131   public:
    132     // _GLIBCXX_RESOLVE_LIB_DEFECTS
    133     // 3414. service_already_exists has no usable constructors
    134     service_already_exists() : logic_error("service already exists") { }
    135   };
    136 
    137   template<typename _Tp> struct is_executor;
    138 
    139   struct executor_arg_t { };
    140 
    141   constexpr executor_arg_t executor_arg = executor_arg_t();
    142 
    143   /// Trait for determining whether to construct an object with an executor.
    144   template<typename _Tp, typename _Executor> struct uses_executor;
    145 
    146   template<typename _Tp, typename _Executor, typename = __void_t<>>
    147     struct __associated_executor_impl
    148     {
    149       using type = _Executor;
    150 
    151       static type
    152       _S_get(const _Tp&, const _Executor& __e) noexcept { return __e; }
    153     };
    154 
    155   template<typename _Tp, typename _Executor>
    156     struct __associated_executor_impl<_Tp, _Executor,
    157 				       __void_t<typename _Tp::executor_type>>
    158     {
    159       using type = typename _Tp::executor_type;
    160 
    161       static type
    162       _S_get(const _Tp& __t, const _Executor&) noexcept
    163       { return __t.get_executor(); }
    164     };
    165 
    166   /// Helper to associate an executor with a type.
    167   template<typename _Tp, typename _Executor = system_executor>
    168     struct associated_executor
    169     : __associated_executor_impl<_Tp, _Executor>
    170     {
    171       static auto
    172       get(const _Tp& __t, const _Executor& __e = _Executor()) noexcept
    173       { return __associated_executor_impl<_Tp, _Executor>::_S_get(__t, __e); }
    174     };
    175 
    176 
    177   template<typename _Tp, typename _Executor = system_executor>
    178     using associated_executor_t
    179       = typename associated_executor<_Tp, _Executor>::type;
    180 
    181   template<typename _ExecutionContext>
    182     using __is_exec_context
    183       = is_convertible<_ExecutionContext&, execution_context&>;
    184 
    185   template<typename _Tp>
    186     using __executor_t = typename _Tp::executor_type;
    187 
    188   // get_associated_executor:
    189 
    190   template<typename _Tp>
    191     inline associated_executor_t<_Tp>
    192     get_associated_executor(const _Tp& __t) noexcept
    193     { return associated_executor<_Tp>::get(__t); }
    194 
    195   template<typename _Tp, typename _Executor>
    196     inline
    197     enable_if_t<is_executor<_Executor>::value,
    198 		associated_executor_t<_Tp, _Executor>>
    199     get_associated_executor(const _Tp& __t, const _Executor& __ex)
    200     { return associated_executor<_Tp, _Executor>::get(__t, __ex); }
    201 
    202   template<typename _Tp, typename _ExecutionContext>
    203     inline
    204     enable_if_t<__is_exec_context<_ExecutionContext>::value,
    205 		associated_executor_t<_Tp, __executor_t<_ExecutionContext>>>
    206     get_associated_executor(const _Tp& __t, _ExecutionContext& __ctx) noexcept
    207     { return net::get_associated_executor(__t, __ctx.get_executor()); }
    208 
    209 
    210   /// Helper to bind an executor to an object or function.
    211   template<typename _Tp, typename _Executor>
    212     class executor_binder;
    213 
    214   template<typename _Tp, typename _Executor, typename _Signature>
    215     class async_result<executor_binder<_Tp, _Executor>, _Signature>;
    216 
    217   template<typename _Tp, typename _Executor, typename _ProtoAllocator>
    218     struct associated_allocator<executor_binder<_Tp, _Executor>,
    219 				_ProtoAllocator>;
    220 
    221   template<typename _Tp, typename _Executor, typename _Executor1>
    222     struct associated_executor<executor_binder<_Tp, _Executor>, _Executor1>;
    223 
    224   // bind_executor:
    225 
    226   template<typename _Executor, typename _Tp>
    227     inline
    228     enable_if_t<is_executor<_Executor>::value,
    229 		executor_binder<decay_t<_Tp>, _Executor>>
    230     bind_executor(const _Executor& __ex, _Tp&& __t)
    231     { return { std::forward<_Tp>(__t), __ex }; }
    232 
    233   template<typename _ExecutionContext, typename _Tp>
    234     inline
    235     enable_if_t<__is_exec_context<_ExecutionContext>::value,
    236 		executor_binder<decay_t<_Tp>, __executor_t<_ExecutionContext>>>
    237     bind_executor(_ExecutionContext& __ctx, _Tp&& __t)
    238     { return { __ctx.get_executor(), forward<_Tp>(__t) }; }
    239 
    240 
    241   /// A scope-guard type to record when work is started and finished.
    242   template<typename _Executor>
    243     class executor_work_guard;
    244 
    245   // make_work_guard:
    246 
    247   template<typename _Executor>
    248     inline
    249     enable_if_t<is_executor<_Executor>::value, executor_work_guard<_Executor>>
    250     make_work_guard(const _Executor& __ex)
    251     { return executor_work_guard<_Executor>(__ex); }
    252 
    253   template<typename _ExecutionContext>
    254     inline
    255     enable_if_t<__is_exec_context<_ExecutionContext>::value,
    256 		executor_work_guard<__executor_t<_ExecutionContext>>>
    257     make_work_guard(_ExecutionContext& __ctx)
    258     { return net::make_work_guard(__ctx.get_executor()); }
    259 
    260   template<typename _Tp>
    261     inline
    262     enable_if_t<__not_<__or_<is_executor<_Tp>, __is_exec_context<_Tp>>>::value,
    263 		executor_work_guard<associated_executor_t<_Tp>>>
    264     make_work_guard(const _Tp& __t)
    265     { return net::get_associated_executor(__t); }
    266 
    267   template<typename _Tp, typename _Up>
    268     auto
    269     make_work_guard(const _Tp& __t, _Up&& __u)
    270     -> decltype(net::make_work_guard(
    271 	  net::get_associated_executor(__t, forward<_Up>(__u))))
    272     {
    273       return net::make_work_guard(
    274 	  net::get_associated_executor(__t, forward<_Up>(__u)));
    275     }
    276 
    277   /// Allows function objects to execute on any thread.
    278   class system_executor;
    279 
    280   /// The execution context associated with system_executor objects.
    281   class system_context;
    282 
    283   inline bool
    284   operator==(const system_executor&, const system_executor&) { return true; }
    285 
    286   inline bool
    287   operator!=(const system_executor&, const system_executor&) { return false; }
    288 
    289   /// Exception thrown by empty executors.
    290   class bad_executor;
    291 
    292   /// Polymorphic wrapper for types satisfying the Executor requirements.
    293   class executor;
    294 
    295   bool
    296   operator==(const executor&, const executor&) noexcept;
    297 
    298   bool
    299   operator==(const executor&, nullptr_t) noexcept;
    300 
    301   bool
    302   operator==(nullptr_t, const executor&) noexcept;
    303 
    304   bool
    305   operator!=(const executor&, const executor&) noexcept;
    306 
    307   bool
    308   operator!=(const executor&, nullptr_t) noexcept;
    309 
    310   bool
    311   operator!=(nullptr_t, const executor&) noexcept;
    312 
    313   void swap(executor&, executor&) noexcept;
    314 
    315   // dispatch:
    316 
    317   template<typename _CompletionToken>
    318     __deduced_t<_CompletionToken, void()>
    319     dispatch(_CompletionToken&& __token);
    320 
    321   template<typename _Executor, typename _CompletionToken>
    322     __deduced_t<_CompletionToken, void()>
    323     dispatch(const _Executor& __ex, _CompletionToken&& __token);
    324 
    325   template<typename _ExecutionContext, typename _CompletionToken>
    326     __deduced_t<_CompletionToken, void()>
    327     dispatch(_ExecutionContext& __ctx, _CompletionToken&& __token);
    328 
    329   // post:
    330 
    331   template<typename _CompletionToken>
    332     __deduced_t<_CompletionToken, void()>
    333     post(_CompletionToken&& __token);
    334   template<typename _Executor, typename _CompletionToken>
    335     enable_if_t<is_executor<_Executor>::value,
    336 		__deduced_t<_CompletionToken, void()>>
    337     post(const _Executor& __ex, _CompletionToken&& __token);
    338   template<typename _ExecutionContext, typename _CompletionToken>
    339     enable_if_t<__is_exec_context<_ExecutionContext>::value,
    340 		__deduced_t<_CompletionToken, void()>>
    341     post(_ExecutionContext& __ctx, _CompletionToken&& __token);
    342 
    343   // defer:
    344 
    345   template<typename _CompletionToken>
    346     __deduced_t<_CompletionToken, void()>
    347     defer(_CompletionToken&& __token);
    348   template<typename _Executor, typename _CompletionToken>
    349     __deduced_t<_CompletionToken, void()>
    350     defer(const _Executor& __ex, _CompletionToken&& __token);
    351   template<typename _ExecutionContext, typename _CompletionToken>
    352     __deduced_t<_CompletionToken, void()>
    353     defer(_ExecutionContext& __ctx, _CompletionToken&& __token);
    354 
    355   template<typename _Executor>
    356     class strand;
    357 
    358   template<typename _Executor>
    359     bool
    360     operator==(const strand<_Executor>& __a, const strand<_Executor>& __b);
    361 
    362   template<typename _Executor>
    363     bool
    364     operator!=(const strand<_Executor>& __a, const strand<_Executor>& __b)
    365     { return !(__a == __b); }
    366 
    367   template<typename _CompletionToken, typename _Signature, typename>
    368     class async_result
    369     {
    370     public:
    371       using completion_handler_type = _CompletionToken;
    372       using return_type = void;
    373 
    374       explicit async_result(completion_handler_type&) {}
    375       async_result(const async_result&) = delete;
    376       async_result& operator=(const async_result&) = delete;
    377 
    378       return_type get() {}
    379     };
    380 
    381   template<typename _CompletionToken, typename _Signature>
    382     class async_completion
    383     {
    384       using __result_type
    385 	= async_result<decay_t<_CompletionToken>, _Signature>;
    386 
    387     public:
    388       using completion_handler_type
    389 	= typename __result_type::completion_handler_type;
    390 
    391     private:
    392       using __handler_type = __conditional_t<
    393 	is_same<_CompletionToken, completion_handler_type>::value,
    394 	completion_handler_type&,
    395 	completion_handler_type>;
    396 
    397     public:
    398       explicit
    399       async_completion(_CompletionToken& __t)
    400       : completion_handler(std::forward<__handler_type>(__t)),
    401 	result(completion_handler)
    402       { }
    403 
    404       async_completion(const async_completion&) = delete;
    405       async_completion& operator=(const async_completion&) = delete;
    406 
    407       __handler_type	completion_handler;
    408       __result_type	result;
    409     };
    410 
    411 
    412   class execution_context
    413   {
    414   public:
    415     class service
    416     {
    417     protected:
    418       // construct / copy / destroy:
    419 
    420       explicit
    421       service(execution_context& __owner) : _M_context(__owner) { }
    422 
    423       service(const service&) = delete;
    424       service& operator=(const service&) = delete;
    425 
    426       virtual ~service() { } // TODO should not be inline
    427 
    428       // service observers:
    429 
    430       execution_context& context() const noexcept { return _M_context; }
    431 
    432     private:
    433       // service operations:
    434 
    435       virtual void shutdown() noexcept = 0;
    436       virtual void notify_fork(fork_event) { }
    437 
    438       friend class execution_context;
    439       execution_context& _M_context;
    440     };
    441 
    442     // construct / copy / destroy:
    443 
    444     execution_context() { }
    445 
    446     execution_context(const execution_context&) = delete;
    447     execution_context& operator=(const execution_context&) = delete;
    448 
    449     virtual ~execution_context()
    450     {
    451       shutdown();
    452       destroy();
    453     }
    454 
    455     // execution context operations:
    456 
    457     void
    458     notify_fork(fork_event __e)
    459     {
    460       auto __l = [=](auto& __svc) { __svc._M_ptr->notify_fork(__e); };
    461       if (__e == fork_event::prepare)
    462 	std::for_each(_M_services.rbegin(), _M_services.rend(), __l);
    463       else
    464 	std::for_each(_M_services.begin(), _M_services.end(), __l);
    465     }
    466 
    467   protected:
    468     // execution context protected operations:
    469 
    470     void
    471     shutdown()
    472     {
    473       std::for_each(_M_services.rbegin(), _M_services.rend(),
    474 	  [=](auto& __svc) {
    475 	    if (__svc._M_active)
    476 	      {
    477 	        __svc._M_ptr->shutdown();
    478 		__svc._M_active = false;
    479 	      }
    480 	  });
    481     }
    482 
    483     void
    484     destroy()
    485     {
    486       while (_M_services.size())
    487 	_M_services.pop_back();
    488       _M_keys.clear();
    489     }
    490 
    491   protected:
    492 
    493     template<typename _Service>
    494       static void
    495       _S_deleter(service* __svc) { delete static_cast<_Service*>(__svc); }
    496 
    497     struct _ServicePtr
    498     {
    499       template<typename _Service>
    500 	explicit
    501 	_ServicePtr(_Service* __svc)
    502 	: _M_ptr(__svc, &_S_deleter<_Service>), _M_active(true) { }
    503 
    504       std::unique_ptr<service, void(*)(service*)> _M_ptr;
    505       bool _M_active;
    506     };
    507 
    508 #if defined(_GLIBCXX_HAS_GTHREADS)
    509     using mutex_type = std::mutex;
    510 #else
    511     struct mutex_type
    512     {
    513       void lock() const { }
    514       void unlock() const { }
    515     };
    516 #endif
    517     mutable mutex_type _M_mutex;
    518 
    519     // Sorted in order of beginning of service object lifetime.
    520     std::list<_ServicePtr> _M_services;
    521 
    522     template<typename _Service, typename... _Args>
    523       service*
    524       _M_add_svc(_Args&&... __args)
    525       {
    526 	_M_services.push_back(
    527 	    _ServicePtr{new _Service{*this, std::forward<_Args>(__args)...}} );
    528 	return _M_services.back()._M_ptr.get();
    529       }
    530 
    531     using __key_type = void(*)();
    532 
    533     template<typename _Key>
    534       static __key_type
    535       _S_key() { return reinterpret_cast<__key_type>(&_S_key<_Key>); }
    536 
    537     std::unordered_map<__key_type, service*> _M_keys;
    538 
    539     template<typename _Service>
    540       friend typename _Service::key_type&
    541       use_service(execution_context&);
    542 
    543     template<typename _Service, typename... _Args>
    544       friend _Service&
    545       make_service(execution_context&, _Args&&...);
    546 
    547     template<typename _Service>
    548       friend bool
    549       has_service(const execution_context&) noexcept;
    550   };
    551 
    552   // service access:
    553 
    554   template<typename _Service>
    555     typename _Service::key_type&
    556     use_service(execution_context& __ctx)
    557     {
    558       using _Key = typename _Service::key_type;
    559       static_assert(is_base_of<execution_context::service, _Key>::value,
    560 	  "a service type must derive from execution_context::service");
    561       static_assert(is_base_of<_Key, _Service>::value,
    562 	  "a service type must match or derive from its key_type");
    563       auto __key = execution_context::_S_key<_Key>();
    564       lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
    565       auto& __svc = __ctx._M_keys[__key];
    566       if (__svc == nullptr)
    567 	{
    568 	  __try {
    569 	    __svc = __ctx._M_add_svc<_Service>();
    570 	  } __catch(...) {
    571 	    __ctx._M_keys.erase(__key);
    572 	    __throw_exception_again;
    573 	  }
    574 	}
    575       return static_cast<_Key&>(*__svc);
    576     }
    577 
    578   template<typename _Service, typename... _Args>
    579     _Service&
    580     make_service(execution_context& __ctx, _Args&&... __args)
    581     {
    582       using _Key = typename _Service::key_type;
    583       static_assert(is_base_of<execution_context::service, _Key>::value,
    584 	  "a service type must derive from execution_context::service");
    585       static_assert(is_base_of<_Key, _Service>::value,
    586 	  "a service type must match or derive from its key_type");
    587       auto __key = execution_context::_S_key<_Key>();
    588       lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
    589       auto& __svc = __ctx._M_keys[__key];
    590       if (__svc != nullptr)
    591 	throw service_already_exists();
    592       __try {
    593 	__svc = __ctx._M_add_svc<_Service>(std::forward<_Args>(__args)...);
    594       } __catch(...) {
    595 	__ctx._M_keys.erase(__key);
    596 	__throw_exception_again;
    597       }
    598       return static_cast<_Service&>(*__svc);
    599     }
    600 
    601   template<typename _Service>
    602     inline bool
    603     has_service(const execution_context& __ctx) noexcept
    604     {
    605       using _Key = typename _Service::key_type;
    606       static_assert(is_base_of<execution_context::service, _Key>::value,
    607 	  "a service type must derive from execution_context::service");
    608       static_assert(is_base_of<_Key, _Service>::value,
    609 	  "a service type must match or derive from its key_type");
    610       lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
    611       return __ctx._M_keys.count(execution_context::_S_key<_Key>());
    612     }
    613 
    614   template<typename _Tp, typename = __void_t<>>
    615     struct __is_executor_impl : false_type
    616     { };
    617 
    618   // Check Executor requirements.
    619   template<typename _Tp, typename _Up = remove_const_t<_Tp>>
    620     auto
    621     __executor_reqs(_Up* __x = 0, const _Up* __cx = 0, void(*__f)() = 0,
    622 		    const allocator<int>& __a = {})
    623     -> enable_if_t<__is_value_constructible<_Tp>::value, __void_t<
    624       decltype(*__cx == *__cx),
    625       decltype(*__cx != *__cx),
    626       decltype(__x->context()),
    627       decltype(__x->on_work_started()),
    628       decltype(__x->on_work_finished()),
    629       decltype(__x->dispatch(std::move(__f), __a)),
    630       decltype(__x->post(std::move(__f), __a)),
    631       decltype(__x->defer(std::move(__f), __a))
    632     >>;
    633 
    634   template<typename _Tp>
    635     struct __is_executor_impl<_Tp, decltype(__executor_reqs<_Tp>())>
    636     : true_type
    637     { };
    638 
    639   template<typename _Tp>
    640     struct is_executor : __is_executor_impl<_Tp>
    641     { };
    642 
    643   template<typename _Tp>
    644     constexpr bool is_executor_v = is_executor<_Tp>::value;
    645 
    646   template<typename _Tp, typename _Executor, typename = __void_t<>>
    647     struct __uses_executor_impl : false_type
    648     { };
    649 
    650   template<typename _Tp, typename _Executor>
    651     struct __uses_executor_impl<_Tp, _Executor,
    652 				__void_t<typename _Tp::executor_type>>
    653     : is_convertible<_Executor, typename _Tp::executor_type>
    654     { };
    655 
    656   template<typename _Tp, typename _Executor>
    657     struct uses_executor : __uses_executor_impl<_Tp, _Executor>::type
    658     { };
    659 
    660   template<typename _Tp, typename _Executor>
    661     constexpr bool uses_executor_v = uses_executor<_Tp, _Executor>::value;
    662 
    663   template<typename _Tp, typename _Executor>
    664     class executor_binder
    665     {
    666       struct __use_exec { };
    667 
    668     public:
    669       // types:
    670 
    671       using target_type = _Tp;
    672       using executor_type = _Executor;
    673 
    674       // construct / copy / destroy:
    675 
    676       executor_binder(_Tp __t, const _Executor& __ex)
    677       : executor_binder(__use_exec{}, std::move(__t), __ex)
    678       { }
    679 
    680       executor_binder(const executor_binder&) = default;
    681       executor_binder(executor_binder&&) = default;
    682 
    683       template<typename _Up, typename _OtherExecutor>
    684 	executor_binder(const executor_binder<_Up, _OtherExecutor>& __other)
    685 	: executor_binder(__use_exec{}, __other.get(), __other.get_executor())
    686 	{ }
    687 
    688       template<typename _Up, typename _OtherExecutor>
    689 	executor_binder(executor_binder<_Up, _OtherExecutor>&& __other)
    690 	: executor_binder(__use_exec{}, std::move(__other.get()),
    691 			  __other.get_executor())
    692 	{ }
    693 
    694       template<typename _Up, typename _OtherExecutor>
    695 	executor_binder(executor_arg_t, const _Executor& __ex,
    696 			const executor_binder<_Up, _OtherExecutor>& __other)
    697 	: executor_binder(__use_exec{}, __other.get(), __ex)
    698 	{ }
    699 
    700       template<typename _Up, typename _OtherExecutor>
    701 	executor_binder(executor_arg_t, const _Executor& __ex,
    702 			executor_binder<_Up, _OtherExecutor>&& __other)
    703 	: executor_binder(__use_exec{}, std::move(__other.get()), __ex)
    704 	{ }
    705 
    706       ~executor_binder();
    707 
    708       // executor binder access:
    709 
    710       _Tp& get() noexcept { return _M_target; }
    711       const _Tp& get() const noexcept { return _M_target; }
    712       executor_type get_executor() const noexcept { return _M_ex; }
    713 
    714       // executor binder invocation:
    715 
    716       template<class... _Args>
    717 	result_of_t<_Tp&(_Args&&...)>
    718 	operator()(_Args&&... __args)
    719 	{ return std::__invoke(get(), std::forward<_Args>(__args)...); }
    720 
    721       template<class... _Args>
    722 	result_of_t<const _Tp&(_Args&&...)>
    723 	operator()(_Args&&... __args) const
    724 	{ return std::__invoke(get(), std::forward<_Args>(__args)...); }
    725 
    726     private:
    727       template<typename _Up>
    728 	using __use_exec_cond
    729 	  = __and_<uses_executor<_Tp, _Executor>,
    730 		   is_constructible<_Tp, executor_arg_t, _Executor, _Up>>;
    731 
    732       template<typename _Up, typename _Exec, typename =
    733 	       enable_if_t<__use_exec_cond<_Up>::value>>
    734 	executor_binder(__use_exec, _Up&& __u, _Exec&& __ex)
    735 	: _M_ex(std::forward<_Exec>(__ex)),
    736 	  _M_target(executor_arg, _M_ex, std::forward<_Up>(__u))
    737 	{ }
    738 
    739       template<typename _Up, typename _Exec, typename =
    740 	       enable_if_t<!__use_exec_cond<_Up>::value>>
    741 	executor_binder(__use_exec, _Up&& __u, const _Exec& __ex)
    742 	: _M_ex(std::forward<_Exec>(__ex)),
    743 	  _M_target(std::forward<_Up>(__u))
    744 	{ }
    745 
    746       _Executor	_M_ex;
    747       _Tp	_M_target;
    748     };
    749 
    750   template<typename _Tp, typename _Executor, typename _Signature>
    751     class async_result<executor_binder<_Tp, _Executor>, _Signature>
    752     {
    753       using __inner = async_result<_Tp, _Signature>;
    754 
    755     public:
    756       using completion_handler_type =
    757 	executor_binder<typename __inner::completion_handler_type, _Executor>;
    758 
    759       using return_type = typename __inner::return_type;
    760 
    761       explicit
    762       async_result(completion_handler_type& __h)
    763       : _M_target(__h.get()) { }
    764 
    765       async_result(const async_result&) = delete;
    766       async_result& operator=(const async_result&) = delete;
    767 
    768       return_type get() { return _M_target.get(); }
    769 
    770     private:
    771       __inner _M_target;
    772     };
    773 
    774   template<typename _Tp, typename _Executor, typename _ProtoAlloc>
    775     struct associated_allocator<executor_binder<_Tp, _Executor>, _ProtoAlloc>
    776     {
    777       using type = associated_allocator_t<_Tp, _ProtoAlloc>;
    778 
    779       static type
    780       get(const executor_binder<_Tp, _Executor>& __b,
    781 	  const _ProtoAlloc& __a = _ProtoAlloc()) noexcept
    782       { return associated_allocator<_Tp, _ProtoAlloc>::get(__b.get(), __a); }
    783     };
    784 
    785   template<typename _Tp, typename _Executor, typename _Executor1>
    786     struct associated_executor<executor_binder<_Tp, _Executor>, _Executor1>
    787     {
    788       using type = _Executor;
    789 
    790       static type
    791       get(const executor_binder<_Tp, _Executor>& __b,
    792 	  const _Executor1& = _Executor1()) noexcept
    793       { return __b.get_executor(); }
    794     };
    795 
    796   template<typename _Executor>
    797     class executor_work_guard
    798     {
    799     public:
    800       // types:
    801 
    802       using executor_type = _Executor;
    803 
    804       // construct / copy / destroy:
    805 
    806       explicit
    807       executor_work_guard(const executor_type& __ex) noexcept
    808       : _M_ex(__ex), _M_owns(true)
    809       { _M_ex.on_work_started(); }
    810 
    811       executor_work_guard(const executor_work_guard& __other) noexcept
    812       : _M_ex(__other._M_ex), _M_owns(__other._M_owns)
    813       {
    814 	if (_M_owns)
    815 	  _M_ex.on_work_started();
    816       }
    817 
    818       executor_work_guard(executor_work_guard&& __other) noexcept
    819       : _M_ex(__other._M_ex), _M_owns(__other._M_owns)
    820       { __other._M_owns = false; }
    821 
    822       executor_work_guard& operator=(const executor_work_guard&) = delete;
    823 
    824       ~executor_work_guard()
    825       {
    826 	if (_M_owns)
    827 	  _M_ex.on_work_finished();
    828       }
    829 
    830       // executor work guard observers:
    831 
    832       executor_type get_executor() const noexcept { return _M_ex; }
    833 
    834       bool owns_work() const noexcept { return _M_owns; }
    835 
    836       // executor work guard modifiers:
    837 
    838       void reset() noexcept
    839       {
    840 	if (_M_owns)
    841 	  _M_ex.on_work_finished();
    842 	_M_owns = false;
    843       }
    844 
    845     private:
    846       _Executor	_M_ex;
    847       bool	_M_owns;
    848     };
    849 
    850 
    851   class system_context : public execution_context
    852   {
    853   public:
    854     // types:
    855 
    856     using executor_type = system_executor;
    857 
    858     // construct / copy / destroy:
    859 
    860     system_context() = delete;
    861     system_context(const system_context&) = delete;
    862     system_context& operator=(const system_context&) = delete;
    863 
    864     ~system_context()
    865     {
    866       stop();
    867       join();
    868     }
    869 
    870     // system_context operations:
    871 
    872     executor_type get_executor() noexcept;
    873 
    874     void stop()
    875     {
    876       lock_guard<mutex_type> __lock(_M_mtx);
    877       _M_stopped = true;
    878       _M_cv.notify_all();
    879     }
    880 
    881     bool stopped() const noexcept
    882     {
    883       lock_guard<mutex_type> __lock(_M_mtx);
    884       return _M_stopped;
    885     }
    886 
    887     void join()
    888     {
    889       if (_M_thread.joinable())
    890 	_M_thread.join();
    891     }
    892 
    893   private:
    894     friend system_executor;
    895 
    896     struct __tag { explicit __tag() = default; };
    897     system_context(__tag) { }
    898 
    899 #ifndef _GLIBCXX_HAS_GTHREADS
    900     struct thread
    901     {
    902       bool joinable() const { return false; }
    903       void join() { }
    904     };
    905     struct condition_variable
    906     {
    907       void notify_all() { }
    908     };
    909 #endif
    910 
    911     thread			_M_thread;
    912     mutable mutex_type		_M_mtx; // XXX can we reuse base's _M_mutex?
    913     condition_variable		_M_cv;
    914     queue<function<void()>>	_M_tasks;
    915     bool			_M_stopped = false;
    916 
    917 #ifdef _GLIBCXX_HAS_GTHREADS
    918     void
    919     _M_run()
    920     {
    921       while (true)
    922 	{
    923 	  function<void()> __f;
    924 	  {
    925 	    unique_lock<mutex_type> __lock(_M_mtx);
    926 	    _M_cv.wait(__lock,
    927 		       [this]{ return _M_stopped || !_M_tasks.empty(); });
    928 	    if (_M_stopped)
    929 	      return;
    930 	    __f = std::move(_M_tasks.front());
    931 	    _M_tasks.pop();
    932 	  }
    933 	  __f();
    934 	}
    935     }
    936 #endif
    937 
    938     void
    939     _M_post(std::function<void()> __f __attribute__((__unused__)))
    940     {
    941       lock_guard<mutex_type> __lock(_M_mtx);
    942       if (_M_stopped)
    943 	return;
    944 #ifdef _GLIBCXX_HAS_GTHREADS
    945       if (!_M_thread.joinable())
    946 	_M_thread = std::thread(&system_context::_M_run, this);
    947       _M_tasks.push(std::move(__f)); // XXX allocator not used
    948       _M_cv.notify_one();
    949 #else
    950       __throw_system_error(EOPNOTSUPP);
    951 #endif
    952     }
    953 
    954     static system_context&
    955     _S_get() noexcept
    956     {
    957       static system_context __sc(__tag{});
    958       return __sc;
    959     }
    960   };
    961 
    962   class system_executor
    963   {
    964   public:
    965     // executor operations:
    966 
    967     system_executor() { }
    968 
    969     system_context&
    970     context() const noexcept { return system_context::_S_get(); }
    971 
    972     void on_work_started() const noexcept { }
    973     void on_work_finished() const noexcept { }
    974 
    975     template<typename _Func, typename _ProtoAlloc>
    976       void
    977       dispatch(_Func&& __f, const _ProtoAlloc& __a) const
    978       { decay_t<_Func>{std::forward<_Func>(__f)}(); }
    979 
    980     template<typename _Func, typename _ProtoAlloc>
    981       void
    982       post(_Func&& __f, const _ProtoAlloc&) const // XXX allocator not used
    983       {
    984 	system_context::_S_get()._M_post(std::forward<_Func>(__f));
    985       }
    986 
    987     template<typename _Func, typename _ProtoAlloc>
    988       void
    989       defer(_Func&& __f, const _ProtoAlloc& __a) const
    990       { post(std::forward<_Func>(__f), __a); }
    991   };
    992 
    993   inline system_executor
    994   system_context::get_executor() noexcept
    995   { return {}; }
    996 
    997   class bad_executor : public std::exception
    998   {
    999     virtual const char* what() const noexcept { return "bad executor"; }
   1000   };
   1001 
   1002   inline void __throw_bad_executor() // TODO make non-inline
   1003   {
   1004 #if __cpp_exceptions
   1005     throw bad_executor();
   1006 #else
   1007     __builtin_abort();
   1008 #endif
   1009   }
   1010 
   1011   class executor
   1012   {
   1013   public:
   1014     // construct / copy / destroy:
   1015 
   1016     executor() noexcept = default;
   1017 
   1018     executor(nullptr_t) noexcept { }
   1019     executor(const executor&) noexcept = default;
   1020     executor(executor&&) noexcept = default;
   1021 
   1022     template<typename _Executor>
   1023       executor(_Executor __e)
   1024       : _M_target(make_shared<_Tgt1<_Executor>>(std::move(__e)))
   1025       { }
   1026 
   1027     template<typename _Executor, typename _ProtoAlloc>
   1028       executor(allocator_arg_t, const _ProtoAlloc& __a, _Executor __e)
   1029       : _M_target(allocate_shared<_Tgt2<_Executor, _ProtoAlloc>>(__a,
   1030 	    std::move(__e), __a))
   1031       { }
   1032 
   1033     executor& operator=(const executor&) noexcept = default;
   1034     executor& operator=(executor&&) noexcept = default;
   1035 
   1036     executor&
   1037     operator=(nullptr_t) noexcept
   1038     {
   1039       _M_target = nullptr;
   1040       return *this;
   1041     }
   1042 
   1043     template<typename _Executor>
   1044       executor&
   1045       operator=(_Executor __e)
   1046       {
   1047 	executor(std::move(__e)).swap(*this);
   1048 	return *this;
   1049       }
   1050 
   1051     ~executor() = default;
   1052 
   1053     // executor modifiers:
   1054 
   1055     void
   1056     swap(executor& __other) noexcept
   1057     { _M_target.swap(__other._M_target); }
   1058 
   1059     template<typename _Executor, typename _Alloc>
   1060       void
   1061       assign(_Executor __e, const _Alloc& __a)
   1062       { executor(allocator_arg, __a, std::move(__e)).swap(*this); }
   1063 
   1064     // executor operations:
   1065 
   1066     execution_context&
   1067     context() const noexcept
   1068     {
   1069       __glibcxx_assert( _M_target );
   1070       return _M_target->context();
   1071     }
   1072 
   1073     void
   1074     on_work_started() const noexcept
   1075     {
   1076       __glibcxx_assert( _M_target );
   1077       return _M_target->on_work_started();
   1078     }
   1079 
   1080     void
   1081     on_work_finished() const noexcept
   1082     {
   1083       __glibcxx_assert( _M_target );
   1084       return _M_target->on_work_finished();
   1085     }
   1086 
   1087     template<typename _Func, typename _Alloc>
   1088       void
   1089       dispatch(_Func&& __f, const _Alloc& __a) const
   1090       {
   1091 	if (!_M_target)
   1092 	  __throw_bad_executor();
   1093 	// _M_target->dispatch({allocator_arg, __a, std::forward<_Func>(__f)});
   1094 	_M_target->dispatch(std::forward<_Func>(__f));
   1095       }
   1096 
   1097     template<typename _Func, typename _Alloc>
   1098       void
   1099       post(_Func&& __f, const _Alloc& __a) const
   1100       {
   1101 	if (!_M_target)
   1102 	  __throw_bad_executor();
   1103 	// _M_target->post({allocator_arg, __a, std::forward<_Func>(__f)});
   1104 	_M_target->post(std::forward<_Func>(__f));
   1105       }
   1106 
   1107     template<typename _Func, typename _Alloc>
   1108       void
   1109       defer(_Func&& __f, const _Alloc& __a) const
   1110       {
   1111 	if (!_M_target)
   1112 	  __throw_bad_executor();
   1113 	// _M_target->defer({allocator_arg, __a, std::forward<_Func>(__f)});
   1114 	_M_target->defer(std::forward<_Func>(__f));
   1115       }
   1116 
   1117     // executor capacity:
   1118 
   1119     explicit operator bool() const noexcept
   1120     { return static_cast<bool>(_M_target); }
   1121 
   1122     // executor target access:
   1123 
   1124 #if __cpp_rtti
   1125     const type_info&
   1126     target_type() const noexcept
   1127     {
   1128       if (_M_target)
   1129 	return *static_cast<const type_info*>(_M_target->target_type());
   1130       return typeid(void);
   1131     }
   1132 #endif
   1133 
   1134     template<typename _Executor>
   1135       _Executor*
   1136       target() noexcept
   1137       {
   1138 	void* __p = nullptr;
   1139 	if (_M_target)
   1140 	  {
   1141 	    if (_M_target->_M_func == &_Tgt1<remove_cv_t<_Executor>>::_S_func)
   1142 	      __p = _M_target->_M_func(_M_target.get(), nullptr);
   1143 #if __cpp_rtti
   1144 	    else
   1145 	      __p = _M_target->target(&typeid(_Executor));
   1146 #endif
   1147 	  }
   1148 	return static_cast<_Executor*>(__p);
   1149       }
   1150 
   1151     template<typename _Executor>
   1152       const _Executor*
   1153       target() const noexcept
   1154       {
   1155 	const void* __p = nullptr;
   1156 	if (_M_target)
   1157 	  {
   1158 	    if (_M_target->_M_func == &_Tgt1<remove_cv_t<_Executor>>::_S_func)
   1159 	      return (_Executor*)_M_target->_M_func(_M_target.get(), nullptr);
   1160 #if __cpp_rtti
   1161 	    else
   1162 	      __p = _M_target->target(&typeid(_Executor));
   1163 #endif
   1164 	  }
   1165 	return static_cast<const _Executor*>(__p);
   1166       }
   1167 
   1168   private:
   1169     struct _Tgt
   1170     {
   1171       virtual void on_work_started() const noexcept = 0;
   1172       virtual void on_work_finished() const noexcept = 0;
   1173       virtual execution_context& context() const noexcept = 0;
   1174       virtual void dispatch(std::function<void()>) const = 0;
   1175       virtual void post(std::function<void()>) const = 0;
   1176       virtual void defer(std::function<void()>) const = 0;
   1177       virtual const void* target_type() const noexcept = 0;
   1178       virtual void* target(const void*) noexcept = 0;
   1179       virtual bool _M_equals(_Tgt*) const noexcept = 0;
   1180 
   1181       using _Func = void* (_Tgt*, const _Tgt*);
   1182       _Func* _M_func; // Provides access to target without RTTI
   1183     };
   1184 
   1185     template<typename _Ex>
   1186       struct _Tgt1 : _Tgt
   1187       {
   1188 	explicit
   1189 	_Tgt1(_Ex&& __ex)
   1190 	: _M_ex(std::move(__ex))
   1191 	{ this->_M_func = &_S_func; }
   1192 
   1193 	void
   1194 	on_work_started() const noexcept override
   1195 	{ _M_ex.on_work_started(); }
   1196 
   1197 	void
   1198 	on_work_finished() const noexcept override
   1199 	{ _M_ex.on_work_finished(); }
   1200 
   1201 	execution_context&
   1202 	context() const noexcept override
   1203 	{ return _M_ex.context(); }
   1204 
   1205 	void
   1206 	dispatch(std::function<void()> __f) const override
   1207 	{ _M_ex.dispatch(std::move(__f), allocator<void>()); }
   1208 
   1209 	void
   1210 	post(std::function<void()> __f) const override
   1211 	{ _M_ex.post(std::move(__f), allocator<void>()); }
   1212 
   1213 	void
   1214 	defer(std::function<void()> __f) const override
   1215 	{ _M_ex.defer(std::move(__f), allocator<void>()); }
   1216 
   1217 	const void*
   1218 	target_type() const noexcept override
   1219 	{
   1220 #if __cpp_rtti
   1221 	  return &typeid(_Ex);
   1222 #else
   1223 	  return nullptr;
   1224 #endif
   1225 	}
   1226 
   1227 	void*
   1228 	target(const void* __ti) noexcept override
   1229 	{
   1230 #if __cpp_rtti
   1231 	  if (*static_cast<const type_info*>(__ti) == typeid(_Ex))
   1232 	    return std::__addressof(_M_ex);
   1233 #endif
   1234 	  return nullptr;
   1235 	}
   1236 
   1237 	bool
   1238 	_M_equals(_Tgt* __tgt) const noexcept override
   1239 	{
   1240 #if __cpp_rtti
   1241 	  if (const void* __p = __tgt->target(&typeid(_Ex)))
   1242 	    return *static_cast<const _Ex*>(__p) == _M_ex;
   1243 #endif
   1244 	  return false;
   1245 	}
   1246 
   1247 	_Ex _M_ex [[__no_unique_address__]];
   1248 
   1249 	static void*
   1250 	_S_func(_Tgt* __p, const _Tgt* __q) noexcept
   1251 	{
   1252 	  auto& __ex = static_cast<_Tgt1*>(__p)->_M_ex;
   1253 	  if (__q)
   1254 	    {
   1255 	      if (__ex == static_cast<const _Tgt1*>(__q)->_M_ex)
   1256 		return __p;
   1257 	      else
   1258 		return nullptr;
   1259 	    }
   1260 	  else
   1261 	    return std::__addressof(__ex);
   1262 	}
   1263       };
   1264 
   1265     template<typename _Ex, typename _Alloc>
   1266       struct _Tgt2 : _Tgt1<_Ex>
   1267       {
   1268 	explicit
   1269 	_Tgt2(_Ex&& __ex, const _Alloc& __a)
   1270 	: _Tgt1<_Ex>(std::move(__ex)), _M_alloc(__a) { }
   1271 
   1272 	void
   1273 	dispatch(std::function<void()> __f) const override
   1274 	{ this->_M_ex.dispatch(std::move(__f), _M_alloc); }
   1275 
   1276 	void
   1277 	post(std::function<void()> __f) const override
   1278 	{ this->_M_ex.post(std::move(__f), _M_alloc); }
   1279 
   1280 	void
   1281 	defer(std::function<void()> __f) const override
   1282 	{ this->_M_ex.defer(std::move(__f), _M_alloc); }
   1283 
   1284 	_Alloc _M_alloc [[__no_unique_address__]];
   1285       };
   1286 
   1287     // Partial specialization for std::allocator<T>.
   1288     // Don't store the allocator.
   1289     template<typename _Ex, typename _Tp>
   1290       struct _Tgt2<_Ex, std::allocator<_Tp>> : _Tgt1<_Ex>
   1291       { };
   1292 
   1293     friend bool
   1294     operator==(const executor& __a, const executor& __b) noexcept
   1295     {
   1296       _Tgt* __ta = __a._M_target.get();
   1297       _Tgt* __tb = __b._M_target.get();
   1298       if (__ta == __tb)
   1299 	return true;
   1300       if (!__ta || !__tb)
   1301 	return false;
   1302       if (__ta->_M_func == __tb->_M_func)
   1303 	return __ta->_M_func(__ta, __tb);
   1304       return __ta->_M_equals(__tb);
   1305     }
   1306 
   1307     shared_ptr<_Tgt> _M_target;
   1308   };
   1309 
   1310   template<> struct is_executor<executor> : true_type { };
   1311 
   1312   /// executor comparisons
   1313   inline bool
   1314   operator==(const executor& __e, nullptr_t) noexcept
   1315   { return !__e; }
   1316 
   1317   inline bool
   1318   operator==(nullptr_t, const executor& __e) noexcept
   1319   { return !__e; }
   1320 
   1321   inline bool
   1322   operator!=(const executor& __a, const executor& __b) noexcept
   1323   { return !(__a == __b); }
   1324 
   1325   inline bool
   1326   operator!=(const executor& __e, nullptr_t) noexcept
   1327   { return (bool)__e; }
   1328 
   1329   inline bool
   1330   operator!=(nullptr_t, const executor& __e) noexcept
   1331   { return (bool)__e; }
   1332 
   1333   /// Swap two executor objects.
   1334   inline void swap(executor& __a, executor& __b) noexcept { __a.swap(__b); }
   1335 
   1336 
   1337   template<typename _CompletionHandler>
   1338     struct __dispatcher
   1339     {
   1340       explicit
   1341       __dispatcher(_CompletionHandler& __h)
   1342       : _M_h(std::move(__h)), _M_w(net::make_work_guard(_M_h))
   1343       { }
   1344 
   1345       void operator()()
   1346       {
   1347 	auto __alloc = net::get_associated_allocator(_M_h);
   1348 	_M_w.get_executor().dispatch(std::move(_M_h), __alloc);
   1349 	_M_w.reset();
   1350       }
   1351 
   1352       _CompletionHandler _M_h;
   1353       decltype(net::make_work_guard(_M_h)) _M_w;
   1354     };
   1355 
   1356   template<typename _CompletionHandler>
   1357     inline __dispatcher<_CompletionHandler>
   1358     __make_dispatcher(_CompletionHandler& __h)
   1359     { return __dispatcher<_CompletionHandler>{__h}; }
   1360 
   1361 
   1362 
   1363   // dispatch:
   1364 
   1365   template<typename _CompletionToken>
   1366     inline __deduced_t<_CompletionToken, void()>
   1367     dispatch(_CompletionToken&& __token)
   1368     {
   1369       async_completion<_CompletionToken, void()> __cmpl{__token};
   1370       auto __ex = net::get_associated_executor(__cmpl.completion_handler);
   1371       auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
   1372       __ex.dispatch(std::move(__cmpl.completion_handler), __alloc);
   1373       return __cmpl.result.get();
   1374     }
   1375 
   1376   template<typename _Executor, typename _CompletionToken>
   1377     inline
   1378     enable_if_t<is_executor<_Executor>::value,
   1379 		__deduced_t<_CompletionToken, void()>>
   1380     dispatch(const _Executor& __ex, _CompletionToken&& __token)
   1381     {
   1382       async_completion<_CompletionToken, void()> __cmpl{__token};
   1383       auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
   1384       __ex.dispatch(net::__make_dispatcher(__cmpl.completion_handler),
   1385 		    __alloc);
   1386       return __cmpl.result.get();
   1387     }
   1388 
   1389   template<typename _ExecutionContext, typename _CompletionToken>
   1390     inline
   1391     enable_if_t<__is_exec_context<_ExecutionContext>::value,
   1392 		__deduced_t<_CompletionToken, void()>>
   1393     dispatch(_ExecutionContext& __ctx, _CompletionToken&& __token)
   1394     {
   1395       return net::dispatch(__ctx.get_executor(),
   1396 			   forward<_CompletionToken>(__token));
   1397     }
   1398 
   1399   // post:
   1400 
   1401   template<typename _CompletionToken>
   1402     inline __deduced_t<_CompletionToken, void()>
   1403     post(_CompletionToken&& __token)
   1404     {
   1405       async_completion<_CompletionToken, void()> __cmpl{__token};
   1406       auto __ex = net::get_associated_executor(__cmpl.completion_handler);
   1407       auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
   1408       __ex.post(std::move(__cmpl.completion_handler), __alloc);
   1409       return __cmpl.result.get();
   1410     }
   1411 
   1412   template<typename _Executor, typename _CompletionToken>
   1413     inline
   1414     enable_if_t<is_executor<_Executor>::value,
   1415 		__deduced_t<_CompletionToken, void()>>
   1416     post(const _Executor& __ex, _CompletionToken&& __token)
   1417     {
   1418       async_completion<_CompletionToken, void()> __cmpl{__token};
   1419       auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
   1420       __ex.post(net::__make_dispatcher(__cmpl.completion_handler), __alloc);
   1421       return __cmpl.result.get();
   1422     }
   1423 
   1424   template<typename _ExecutionContext, typename _CompletionToken>
   1425     inline
   1426     enable_if_t<__is_exec_context<_ExecutionContext>::value,
   1427 		__deduced_t<_CompletionToken, void()>>
   1428     post(_ExecutionContext& __ctx, _CompletionToken&& __token)
   1429     {
   1430       return net::post(__ctx.get_executor(),
   1431 		       forward<_CompletionToken>(__token));
   1432     }
   1433 
   1434   // defer:
   1435 
   1436   template<typename _CompletionToken>
   1437     inline __deduced_t<_CompletionToken, void()>
   1438     defer(_CompletionToken&& __token)
   1439     {
   1440       async_completion<_CompletionToken, void()> __cmpl{__token};
   1441       auto __ex = net::get_associated_executor(__cmpl.completion_handler);
   1442       auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
   1443       __ex.defer(std::move(__cmpl.completion_handler), __alloc);
   1444       return __cmpl.result.get();
   1445     }
   1446 
   1447   template<typename _Executor, typename _CompletionToken>
   1448     inline
   1449     enable_if_t<is_executor<_Executor>::value,
   1450 		__deduced_t<_CompletionToken, void()>>
   1451     defer(const _Executor& __ex, _CompletionToken&& __token)
   1452     {
   1453       async_completion<_CompletionToken, void()> __cmpl{__token};
   1454       auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
   1455       __ex.defer(net::__make_dispatcher(__cmpl.completion_handler), __alloc);
   1456       return __cmpl.result.get();
   1457     }
   1458 
   1459   template<typename _ExecutionContext, typename _CompletionToken>
   1460     inline
   1461     enable_if_t<__is_exec_context<_ExecutionContext>::value,
   1462 		__deduced_t<_CompletionToken, void()>>
   1463     defer(_ExecutionContext& __ctx, _CompletionToken&& __token)
   1464     {
   1465       return net::defer(__ctx.get_executor(),
   1466 			forward<_CompletionToken>(__token));
   1467     }
   1468 
   1469 
   1470   template<typename _Executor>
   1471     class strand
   1472     {
   1473     public:
   1474       // types:
   1475 
   1476       using inner_executor_type = _Executor;
   1477 
   1478       // construct / copy / destroy:
   1479 
   1480       strand(); // TODO make state
   1481 
   1482       explicit strand(_Executor __ex) : _M_inner_ex(__ex) { } // TODO make state
   1483 
   1484       template<typename _Alloc>
   1485 	strand(allocator_arg_t, const _Alloc& __a, _Executor __ex)
   1486 	: _M_inner_ex(__ex) { } // TODO make state
   1487 
   1488       strand(const strand& __other) noexcept
   1489       : _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }
   1490 
   1491       strand(strand&& __other) noexcept
   1492       : _M_state(std::move(__other._M_state)),
   1493 	_M_inner_ex(std::move(__other._M_inner_ex)) { }
   1494 
   1495       template<typename _OtherExecutor>
   1496 	strand(const strand<_OtherExecutor>& __other) noexcept
   1497 	: _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }
   1498 
   1499       template<typename _OtherExecutor>
   1500 	strand(strand<_OtherExecutor>&& __other) noexcept
   1501 	: _M_state(std::move(__other._M_state)),
   1502 	  _M_inner_ex(std::move(__other._M_inner_ex)) { }
   1503 
   1504       strand&
   1505       operator=(const strand& __other) noexcept
   1506       {
   1507 	static_assert(is_copy_assignable<_Executor>::value,
   1508 		      "inner executor type must be CopyAssignable");
   1509 
   1510 	// TODO lock __other
   1511 	// TODO copy state
   1512 	_M_inner_ex = __other._M_inner_ex;
   1513 	return *this;
   1514       }
   1515 
   1516       strand&
   1517       operator=(strand&& __other) noexcept
   1518       {
   1519 	static_assert(is_move_assignable<_Executor>::value,
   1520 		      "inner executor type must be MoveAssignable");
   1521 
   1522 	// TODO move state
   1523 	_M_inner_ex = std::move(__other._M_inner_ex);
   1524 	return *this;
   1525       }
   1526 
   1527       template<typename _OtherExecutor>
   1528 	strand&
   1529 	operator=(const strand<_OtherExecutor>& __other) noexcept
   1530 	{
   1531 	  static_assert(is_convertible<_OtherExecutor, _Executor>::value,
   1532 			"inner executor type must be compatible");
   1533 
   1534 	  // TODO lock __other
   1535 	  // TODO copy state
   1536 	  _M_inner_ex = __other._M_inner_ex;
   1537 	  return *this;
   1538 	}
   1539 
   1540       template<typename _OtherExecutor>
   1541 	strand&
   1542 	operator=(strand<_OtherExecutor>&& __other) noexcept
   1543 	{
   1544 	  static_assert(is_convertible<_OtherExecutor, _Executor>::value,
   1545 			"inner executor type must be compatible");
   1546 
   1547 	  // TODO move state
   1548 	  _M_inner_ex = std::move(__other._M_inner_ex);
   1549 	  return *this;
   1550 	}
   1551 
   1552       ~strand()
   1553       {
   1554 	// the task queue outlives this object if non-empty
   1555 	// TODO create circular ref in queue?
   1556       }
   1557 
   1558       // strand operations:
   1559 
   1560       inner_executor_type
   1561       get_inner_executor() const noexcept
   1562       { return _M_inner_ex; }
   1563 
   1564       bool
   1565       running_in_this_thread() const noexcept
   1566       { return _M_state->running_in_this_thread(); }
   1567 
   1568       execution_context&
   1569       context() const noexcept
   1570       { return _M_inner_ex.context(); }
   1571 
   1572       void on_work_started() const noexcept { _M_inner_ex.on_work_started(); }
   1573       void on_work_finished() const noexcept { _M_inner_ex.on_work_finished(); }
   1574 
   1575       template<typename _Func, typename _Alloc>
   1576 	void
   1577 	dispatch(_Func&& __f, const _Alloc& __a) const
   1578 	{
   1579 	  if (running_in_this_thread())
   1580 	    decay_t<_Func>{std::forward<_Func>(__f)}();
   1581 	  else
   1582 	    post(std::forward<_Func>(__f), __a);
   1583 	}
   1584 
   1585       template<typename _Func, typename _Alloc>
   1586 	void
   1587 	post(_Func&& __f, const _Alloc& __a) const; // TODO
   1588 
   1589       template<typename _Func, typename _Alloc>
   1590 	void
   1591 	defer(_Func&& __f, const _Alloc& __a) const
   1592 	{ post(std::forward<_Func>(__f), __a); }
   1593 
   1594     private:
   1595       friend bool
   1596       operator==(const strand& __a, const strand& __b)
   1597       { return __a._M_state == __b._M_state; }
   1598 
   1599       // TODO add synchronised queue
   1600       struct _State
   1601       {
   1602 #if defined(_GLIBCXX_HAS_GTHREADS)
   1603 	bool
   1604 	running_in_this_thread() const noexcept
   1605 	{ return std::this_thread::get_id() == _M_running_on; }
   1606 
   1607 	std::thread::id _M_running_on;
   1608 #else
   1609 	bool running_in_this_thread() const { return true; }
   1610 #endif
   1611       };
   1612       shared_ptr<_State> _M_state;
   1613       _Executor _M_inner_ex;
   1614     };
   1615 
   1616 #if defined(_GLIBCXX_HAS_GTHREADS)
   1617 
   1618   // Completion token for asynchronous operations initiated with use_future.
   1619   template<typename _Func, typename _Alloc>
   1620     struct __use_future_ct
   1621     {
   1622       std::tuple<_Func, _Alloc> _M_t;
   1623     };
   1624 
   1625   template<typename _Func, typename _Tp>
   1626     struct __use_future_ct<_Func, std::allocator<_Tp>>
   1627     {
   1628       _Func _M_f;
   1629     };
   1630 
   1631   template<typename _ProtoAllocator = allocator<void>>
   1632     class use_future_t
   1633     {
   1634     public:
   1635       // use_future_t types:
   1636       using allocator_type = _ProtoAllocator;
   1637 
   1638       // use_future_t members:
   1639       constexpr
   1640       use_future_t()
   1641       noexcept(is_nothrow_default_constructible<_ProtoAllocator>::value)
   1642       : _M_alloc() { }
   1643 
   1644       explicit
   1645       use_future_t(const _ProtoAllocator& __a) noexcept : _M_alloc(__a) { }
   1646 
   1647       template<typename _OtherAllocator>
   1648 	use_future_t<_OtherAllocator>
   1649 	rebind(const _OtherAllocator& __a) const noexcept
   1650 	{ return use_future_t<_OtherAllocator>(__a); }
   1651 
   1652       allocator_type get_allocator() const noexcept { return _M_alloc; }
   1653 
   1654       template<typename _Func>
   1655 	auto
   1656 	operator()(_Func&& __f) const
   1657 	{
   1658 	  using _Token = __use_future_ct<decay_t<_Func>, _ProtoAllocator>;
   1659 	  return _Token{ {std::forward<_Func>(__f), _M_alloc} };
   1660 	}
   1661 
   1662     private:
   1663       _ProtoAllocator _M_alloc;
   1664     };
   1665 
   1666   template<typename _Tp>
   1667     class use_future_t<std::allocator<_Tp>>
   1668     {
   1669     public:
   1670       // use_future_t types:
   1671       using allocator_type = std::allocator<_Tp>;
   1672 
   1673       // use_future_t members:
   1674       constexpr use_future_t() noexcept = default;
   1675 
   1676       explicit
   1677       use_future_t(const allocator_type& __a) noexcept { }
   1678 
   1679       template<class _Up>
   1680 	use_future_t<std::allocator<_Up>>
   1681 	rebind(const std::allocator<_Up>& __a) const noexcept
   1682 	{ return use_future_t<std::allocator<_Up>>(__a); }
   1683 
   1684       allocator_type get_allocator() const noexcept { return {}; }
   1685 
   1686       template<typename _Func>
   1687 	auto
   1688 	operator()(_Func&& __f) const
   1689 	{
   1690 	  using _Token = __use_future_ct<decay_t<_Func>, allocator_type>;
   1691 	  return _Token{std::forward<_Func>(__f)};
   1692 	}
   1693     };
   1694 
   1695   constexpr use_future_t<> use_future = use_future_t<>();
   1696 
   1697   template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
   1698     class async_result<__use_future_ct<_Func, _Alloc>, _Res(_Args...)>;
   1699 
   1700   template<typename _Result, typename _Executor>
   1701     struct __use_future_ex;
   1702 
   1703   // Completion handler for asynchronous operations initiated with use_future.
   1704   template<typename _Func, typename... _Args>
   1705     struct __use_future_ch
   1706     {
   1707       template<typename _Alloc>
   1708 	explicit
   1709 	__use_future_ch(__use_future_ct<_Func, _Alloc>&& __token)
   1710 	: _M_f{ std::move(std::get<0>(__token._M_t)) },
   1711 	  _M_promise{ std::get<1>(__token._M_t) }
   1712 	{ }
   1713 
   1714       template<typename _Tp>
   1715 	explicit
   1716 	__use_future_ch(__use_future_ct<_Func, std::allocator<_Tp>>&& __token)
   1717 	: _M_f{ std::move(__token._M_f) }
   1718 	{ }
   1719 
   1720       void
   1721       operator()(_Args&&... __args)
   1722       {
   1723 	__try
   1724 	  {
   1725 	    _M_promise.set_value(_M_f(std::forward<_Args>(__args)...));
   1726 	  }
   1727 	__catch(__cxxabiv1::__forced_unwind&)
   1728 	  {
   1729 	    __throw_exception_again;
   1730 	  }
   1731 	__catch(...)
   1732 	  {
   1733 	    _M_promise.set_exception(std::current_exception());
   1734 	  }
   1735       }
   1736 
   1737       using __result = result_of_t<_Func(decay_t<_Args>...)>;
   1738 
   1739       future<__result> get_future() { return _M_promise.get_future(); }
   1740 
   1741     private:
   1742       template<typename _Result, typename _Executor>
   1743 	friend struct __use_future_ex;
   1744 
   1745       _Func _M_f;
   1746       mutable promise<__result> _M_promise;
   1747     };
   1748 
   1749   // Specialization of async_result for operations initiated with use_future.
   1750   template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
   1751     class async_result<__use_future_ct<_Func, _Alloc>, _Res(_Args...)>
   1752     {
   1753     public:
   1754       using completion_handler_type = __use_future_ch<_Func, _Args...>;
   1755       using return_type = future<typename completion_handler_type::__result>;
   1756 
   1757       explicit
   1758       async_result(completion_handler_type& __h)
   1759       : _M_future(__h.get_future())
   1760       { }
   1761 
   1762       async_result(const async_result&) = delete;
   1763       async_result& operator=(const async_result&) = delete;
   1764 
   1765       return_type get() { return std::move(_M_future); }
   1766 
   1767     private:
   1768       return_type _M_future;
   1769     };
   1770 
   1771   template<typename _Result, typename _Executor>
   1772     struct __use_future_ex
   1773     {
   1774       template<typename _Handler>
   1775       __use_future_ex(const _Handler& __h, _Executor __ex)
   1776       : _M_t(__h._M_promise, __ex)
   1777       { }
   1778 
   1779       template<typename _Fn, typename _Alloc>
   1780 	void
   1781 	dispatch(_Fn&& __fn)
   1782 	{
   1783 	  __try
   1784 	    {
   1785 	      std::get<1>(_M_t).dispatch(std::forward<_Fn>(__fn));
   1786 	    }
   1787 	  __catch(__cxxabiv1::__forced_unwind&)
   1788 	    {
   1789 	      __throw_exception_again;
   1790 	    }
   1791 	  __catch(...)
   1792 	    {
   1793 	      std::get<0>(_M_t).set_exception(std::current_exception());
   1794 	    }
   1795 	}
   1796 
   1797       template<typename _Fn, typename _Alloc>
   1798 	void
   1799 	post(_Fn&& __fn)
   1800 	{
   1801 	  __try
   1802 	    {
   1803 	      std::get<1>(_M_t).post(std::forward<_Fn>(__fn));
   1804 	    }
   1805 	  __catch(__cxxabiv1::__forced_unwind&)
   1806 	    {
   1807 	      __throw_exception_again;
   1808 	    }
   1809 	  __catch(...)
   1810 	    {
   1811 	      std::get<0>(_M_t).set_exception(std::current_exception());
   1812 	    }
   1813 	}
   1814 
   1815       template<typename _Fn, typename _Alloc>
   1816 	void
   1817 	defer(_Fn&& __fn)
   1818 	{
   1819 	  __try
   1820 	    {
   1821 	      std::get<1>(_M_t).defer(std::forward<_Fn>(__fn));
   1822 	    }
   1823 	  __catch(__cxxabiv1::__forced_unwind&)
   1824 	    {
   1825 	      __throw_exception_again;
   1826 	    }
   1827 	  __catch(...)
   1828 	    {
   1829 	      std::get<0>(_M_t).set_exception(std::current_exception());
   1830 	    }
   1831 	}
   1832 
   1833     private:
   1834       tuple<promise<_Result>&, _Executor> _M_t;
   1835     };
   1836 
   1837   template<typename _Func, typename... _Args, typename _Executor>
   1838     struct associated_executor<__use_future_ch<_Func, _Args...>, _Executor>
   1839     {
   1840     private:
   1841       using __handler = __use_future_ch<_Func, _Args...>;
   1842 
   1843       using type = __use_future_ex<typename __handler::__result, _Executor>;
   1844 
   1845       static type
   1846       get(const __handler& __h, const _Executor& __ex)
   1847       { return { __h, __ex }; }
   1848     };
   1849 
   1850 #if 0
   1851 
   1852   // [async.use.future.traits]
   1853   template<typename _Allocator, typename _Ret, typename... _Args>
   1854     class handler_type<use_future_t<_Allocator>, _Ret(_Args...)> // TODO uglify name
   1855     {
   1856       template<typename... _Args>
   1857 	struct __is_error_result : false_type { };
   1858 
   1859       template<typename... _Args>
   1860 	struct __is_error_result<error_code, _Args...> : true_type { };
   1861 
   1862       template<typename... _Args>
   1863 	struct __is_error_result<exception_ptr, _Args...> : true_type { };
   1864 
   1865       static exception_ptr
   1866       _S_exptr(exception_ptr& __ex)
   1867       { return std::move(__ex); }
   1868 
   1869       static exception_ptr
   1870       _S_exptr(const error_code& __ec)
   1871       { return make_exception_ptr(system_error(__ec)); }
   1872 
   1873       template<bool _IsError, typename... _UArgs>
   1874 	struct _Type;
   1875 
   1876       // N == 0
   1877       template<bool _IsError>
   1878 	struct _Type<_IsError>
   1879 	{
   1880 	  std::promise<void> _M_promise;
   1881 
   1882 	  void
   1883 	  operator()()
   1884 	  {
   1885 	    _M_promise.set_value();
   1886 	  }
   1887 	};
   1888 
   1889       // N == 1, U0 is error_code or exception_ptr
   1890       template<typename _UArg0>
   1891 	struct _Type<true, _UArg0>
   1892 	{
   1893 	  std::promise<void> _M_promise;
   1894 
   1895 	  template<typename _Arg0>
   1896 	    void
   1897 	    operator()(_Arg0&& __a0)
   1898 	    {
   1899 	      if (__a0)
   1900 		_M_promise.set_exception(_S_exptr(__a0));
   1901 	      else
   1902 		_M_promise.set_value();
   1903 	    }
   1904 	};
   1905 
   1906       // N == 1, U0 is not error_code or exception_ptr
   1907       template<typename _UArg0>
   1908 	struct _Type<false, _UArg0>
   1909 	{
   1910 	  std::promise<_UArg0> _M_promise;
   1911 
   1912 	  template<typename _Arg0>
   1913 	    void
   1914 	    operator()(_Arg0&& __a0)
   1915 	    {
   1916 	      _M_promise.set_value(std::forward<_Arg0>(__a0));
   1917 	    }
   1918 	};
   1919 
   1920       // N == 2, U0 is error_code or exception_ptr
   1921       template<typename _UArg0, typename _UArg1>
   1922 	struct _Type<true, _UArg0, _UArg1>
   1923 	{
   1924 	  std::promise<_UArg1> _M_promise;
   1925 
   1926 	  template<typename _Arg0, typename _Arg1>
   1927 	    void
   1928 	    operator()(_Arg0&& __a0, _Arg1&& __a1)
   1929 	    {
   1930 	      if (__a0)
   1931 		_M_promise.set_exception(_S_exptr(__a0));
   1932 	      else
   1933 		_M_promise.set_value(std::forward<_Arg1>(__a1));
   1934 	    }
   1935 	};
   1936 
   1937       // N >= 2, U0 is not error_code or exception_ptr
   1938       template<typename... _UArgs>
   1939 	struct _Type<false, _UArgs...>
   1940 	{
   1941 	  static_assert(sizeof...(_UArgs) > 1, "wrong partial specialization");
   1942 
   1943 	  std::promise<tuple<_UArgs...>> _M_promise;
   1944 
   1945 	  template<typename... _Args>
   1946 	    void
   1947 	    operator()(_Args&&... __args)
   1948 	    {
   1949 	      _M_promise.set_value(
   1950 		  std::forward_as_tuple(std::forward<_Args>(__args)...));
   1951 	    }
   1952 	};
   1953 
   1954       // N > 2, U0 is error_code or exception_ptr
   1955       template<typename _UArg0, typename... _UArgs>
   1956 	struct _Type<true, _UArg0, _UArgs...>
   1957 	{
   1958 	  static_assert(sizeof...(_UArgs) > 1, "wrong partial specialization");
   1959 
   1960 	  std::promise<tuple<_UArgs...>> _M_promise;
   1961 
   1962 	  template<typename _Arg0, typename... _Args>
   1963 	    void
   1964 	    operator()(_Arg0&& __a0, _Args&&... __args)
   1965 	    {
   1966 	      if (__a0)
   1967 		_M_promise.set_exception(_S_exptr(__a0));
   1968 	      else
   1969 		_M_promise.set_value(
   1970 		    std::forward_as_tuple(std::forward<_Args>(__args)...));
   1971 	    }
   1972 	};
   1973 
   1974     public:
   1975       using type =
   1976 	_Type<__is_error_result<_Args...>::value, decay_t<_Args>...>;
   1977     };
   1978 
   1979 
   1980   template<typename _Alloc, typename _Ret, typename... _Args>
   1981     struct async_result<use_future_t<_Alloc>, _Ret(_Args...)>
   1982     {
   1983       using completion_handler_type
   1984 	= typename handler_type<use_future_t<_Alloc>, _Ret(_Args...)>::type;
   1985 
   1986       using return_type = void; // XXX TODO ???;
   1987 
   1988       explicit
   1989       async_result(completion_handler_type& __h) : _M_handler(__h) { }
   1990 
   1991       auto get() { return _M_handler._M_provider.get_future(); }
   1992 
   1993       async_result(const async_result&) = delete;
   1994       async_result& operator=(const async_result&) = delete;
   1995 
   1996       return_type get() { return _M_handler._M_promise.get_future(); }
   1997 
   1998     private:
   1999       completion_handler_type& _M_handler;
   2000     };
   2001 
   2002   // TODO specialize associated_executor for
   2003   // async_result<use_future_t<A>, Sig>::completion_handler_type
   2004   // to use a __use_future_ex
   2005   // (probably need to move _Type outside of handler_type so we don't have
   2006   // a non-deduced context)
   2007 
   2008 #endif
   2009 
   2010   // [async.packaged.task.specializations]
   2011   template<typename _Ret, typename... _Args, typename _Signature>
   2012     class async_result<packaged_task<_Ret(_Args...)>, _Signature>
   2013     {
   2014     public:
   2015       using completion_handler_type = packaged_task<_Ret(_Args...)>;
   2016       using return_type = future<_Ret>;
   2017 
   2018       explicit
   2019       async_result(completion_handler_type& __h)
   2020       : _M_future(__h.get_future()) { }
   2021 
   2022       async_result(const async_result&) = delete;
   2023       async_result& operator=(const async_result&) = delete;
   2024 
   2025       return_type get() { return std::move(_M_future); }
   2026 
   2027     private:
   2028       return_type _M_future;
   2029     };
   2030 
   2031 #endif // _GLIBCXX_HAS_GTHREADS
   2032 
   2033   /// @}
   2034 
   2035 } // namespace v1
   2036 } // namespace net
   2037 } // namespace experimental
   2038 
   2039   template<typename _Alloc>
   2040     struct uses_allocator<experimental::net::executor, _Alloc>
   2041     : true_type {};
   2042 
   2043 _GLIBCXX_END_NAMESPACE_VERSION
   2044 } // namespace std
   2045 
   2046 #endif // C++14
   2047 
   2048 #endif // _GLIBCXX_EXPERIMENTAL_EXECUTOR
   2049