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