xref: /netbsd-src/external/gpl3/gcc/dist/libstdc++-v3/include/experimental/executor (revision b1e838363e3c6fc78a55519254d99869742dd33c)
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
50namespace std _GLIBCXX_VISIBILITY(default)
51{
52_GLIBCXX_BEGIN_NAMESPACE_VERSION
53namespace experimental
54{
55namespace net
56{
57inline 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