Allow target to override gnu-user.h crti and crtn
[official-gcc.git] / libstdc++-v3 / include / experimental / executor
bloba9cb583c50d921f16a561560a38eafb94ccaea63
1 // <experimental/executor> -*- C++ -*-
3 // Copyright (C) 2015-2018 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.
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.
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.
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/>.
25 /** @file experimental/executor
26  *  This is a TS C++ Library header.
27  */
29 #ifndef _GLIBCXX_EXPERIMENTAL_EXECUTOR
30 #define _GLIBCXX_EXPERIMENTAL_EXECUTOR 1
32 #pragma GCC system_header
34 #if __cplusplus >= 201402L
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>
50 namespace std _GLIBCXX_VISIBILITY(default)
52 _GLIBCXX_BEGIN_NAMESPACE_VERSION
53 namespace experimental
55 namespace net
57 inline namespace v1
60   /**
61    * @ingroup networking
62    * @{
63    */
65   /// Customization point for asynchronous operations.
66   template<typename _CompletionToken, typename _Signature, typename = void>
67     class async_result;
69   /// Convenience utility to help implement asynchronous operations.
70   template<typename _CompletionToken, typename _Signature>
71     class async_completion;
73   template<typename _Tp, typename _ProtoAlloc, typename = __void_t<>>
74     struct __associated_allocator_impl
75     {
76       using type = _ProtoAlloc;
78       static type
79       _S_get(const _Tp&, const _ProtoAlloc& __a) noexcept { return __a; }
80     };
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;
88       static type
89       _S_get(const _Tp& __t, const _ProtoAlloc&) noexcept
90       { return __t.get_allocator(); }
91     };
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     };
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;
112   // get_associated_allocator:
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); }
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); }
125   enum class fork_event { prepare, parent, child };
127   /// An extensible, type-safe, polymorphic set of services.
128   class execution_context;
130   class service_already_exists : public logic_error { };
132   template<typename _Tp> struct is_executor;
134   struct executor_arg_t { };
136   constexpr executor_arg_t executor_arg = executor_arg_t();
138   /// Trait for determining whether to construct an object with an executor.
139   template<typename _Tp, typename _Executor> struct uses_executor;
141   template<typename _Tp, typename _Executor, typename = __void_t<>>
142     struct __associated_executor_impl
143     {
144       using type = _Executor;
146       static type
147       _S_get(const _Tp&, const _Executor& __e) noexcept { return __e; }
148     };
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;
156       static type
157       _S_get(const _Tp& __t, const _Executor&) noexcept
158       { return __t.get_executor(); }
159     };
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     };
172   template<typename _Tp, typename _Executor = system_executor>
173     using associated_executor_t
174       = typename associated_executor<_Tp, _Executor>::type;
176   template<typename _ExecutionContext>
177     using __is_exec_context
178       = is_convertible<_ExecutionContext&, execution_context&>;
180   template<typename _Tp>
181     using __executor_t = typename _Tp::executor_type;
183   // get_associated_executor:
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); }
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); }
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()); }
205   /// Helper to bind an executor to an object or function.
206   template<typename _Tp, typename _Executor>
207     class executor_binder;
209   template<typename _Tp, typename _Executor, typename _Signature>
210     class async_result<executor_binder<_Tp, _Executor>, _Signature>;
212   template<typename _Tp, typename _Executor, typename _ProtoAllocator>
213     struct associated_allocator<executor_binder<_Tp, _Executor>,
214                                 _ProtoAllocator>;
216   template<typename _Tp, typename _Executor, typename _Executor1>
217     struct associated_executor<executor_binder<_Tp, _Executor>, _Executor1>;
219   // bind_executor:
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 }; }
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) }; }
236   /// A scope-guard type to record when work is started and finished.
237   template<typename _Executor>
238     class executor_work_guard;
240   // make_work_guard:
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); }
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()); }
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); }
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     }
272   /// Allows function objects to execute on any thread.
273   class system_executor;
275   /// The execution context associated with system_executor objects.
276   class system_context;
278   inline bool
279   operator==(const system_executor&, const system_executor&) { return true; }
281   inline bool
282   operator!=(const system_executor&, const system_executor&) { return false; }
284   /// Exception thrown by empty executors.
285   class bad_executor;
287   /// Polymorphic wrapper for types satisfying the Executor requirements.
288   class executor;
290   bool
291   operator==(const executor& __a, const executor& __b) noexcept;
293   bool
294   operator==(const executor& __e, nullptr_t) noexcept;
296   inline bool
297   operator==(nullptr_t, const executor& __e) noexcept
298   { return __e == nullptr; }
300   inline bool
301   operator!=(const executor& __a, const executor& __b) noexcept
302   { return !(__a == __b); }
304   inline bool
305   operator!=(const executor& __e, nullptr_t) noexcept
306   { return !(__e == nullptr); }
308   inline bool
309   operator!=(nullptr_t, const executor& __e) noexcept
310   { return !(__e == nullptr); }
312   void swap(executor&, executor&) noexcept;
314   // dispatch:
316   template<typename _CompletionToken>
317     __deduced_t<_CompletionToken, void()>
318     dispatch(_CompletionToken&& __token);
320   template<typename _Executor, typename _CompletionToken>
321     __deduced_t<_CompletionToken, void()>
322     dispatch(const _Executor& __ex, _CompletionToken&& __token);
324   template<typename _ExecutionContext, typename _CompletionToken>
325     __deduced_t<_CompletionToken, void()>
326     dispatch(_ExecutionContext& __ctx, _CompletionToken&& __token);
328   // post:
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);
342   // defer:
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);
354   template<typename _Executor>
355     class strand;
357   template<typename _Executor>
358     bool
359     operator==(const strand<_Executor>& __a, const strand<_Executor>& __b);
361   template<typename _Executor>
362     bool
363     operator!=(const strand<_Executor>& __a, const strand<_Executor>& __b)
364     { return !(__a == __b); }
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;
373       explicit async_result(completion_handler_type&) {}
374       async_result(const async_result&) = delete;
375       async_result& operator=(const async_result&) = delete;
377       return_type get() {}
378     };
380   template<typename _CompletionToken, typename _Signature>
381     class async_completion
382     {
383       using __result_type
384         = async_result<decay_t<_CompletionToken>, _Signature>;
386     public:
387       using completion_handler_type
388         = typename __result_type::completion_handler_type;
390     private:
391       using __handler_type = conditional_t<
392         is_same<_CompletionToken, completion_handler_type>::value,
393         completion_handler_type&,
394         completion_handler_type>;
396     public:
397       explicit
398       async_completion(_CompletionToken& __t)
399       : completion_handler(std::forward<__handler_type>(__t)),
400         result(completion_handler)
401       { }
403       async_completion(const async_completion&) = delete;
404       async_completion& operator=(const async_completion&) = delete;
406       __handler_type    completion_handler;
407       __result_type     result;
408     };
411   class execution_context
412   {
413   public:
414     class service
415     {
416     protected:
417       // construct / copy / destroy:
419       explicit
420       service(execution_context& __owner) : _M_context(__owner) { }
422       service(const service&) = delete;
423       service& operator=(const service&) = delete;
425       virtual ~service() { } // TODO should not be inline
427       // service observers:
429       execution_context& context() const noexcept { return _M_context; }
431     private:
432       // service operations:
434       virtual void shutdown() noexcept = 0;
435       virtual void notify_fork(fork_event) { }
437       friend class execution_context;
438       execution_context& _M_context;
439     };
441     // construct / copy / destroy:
443     execution_context() { }
445     execution_context(const execution_context&) = delete;
446     execution_context& operator=(const execution_context&) = delete;
448     virtual ~execution_context()
449     {
450       shutdown();
451       destroy();
452     }
454     // execution context operations:
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     }
466   protected:
467     // execution context protected operations:
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     }
482     void
483     destroy()
484     {
485       while (_M_services.size())
486         _M_services.pop_back();
487       _M_keys.clear();
488     }
490   protected:
492     template<typename _Service>
493       static void
494       _S_deleter(service* __svc) { delete static_cast<_Service*>(__svc); }
496     struct _ServicePtr
497     {
498       template<typename _Service>
499         explicit
500         _ServicePtr(_Service* __svc)
501         : _M_ptr(__svc, &_S_deleter<_Service>), _M_active(true) { }
503       std::unique_ptr<service, void(*)(service*)> _M_ptr;
504       bool _M_active;
505     };
507     mutable std::mutex _M_mutex;
509     // Sorted in order of beginning of service object lifetime.
510     std::list<_ServicePtr> _M_services;
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       }
521     using __key_type = void(*)();
523     template<typename _Key>
524       static __key_type
525       _S_key() { return reinterpret_cast<__key_type>(&_S_key<_Key>); }
527     std::unordered_map<__key_type, service*> _M_keys;
529     template<typename _Service>
530       friend typename _Service::key_type&
531       use_service(execution_context&);
533     template<typename _Service, typename... _Args>
534       friend _Service&
535       make_service(execution_context&, _Args&&...);
537     template<typename _Service>
538       friend bool
539       has_service(const execution_context&) noexcept;
540   };
542   // service access:
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     }
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     }
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     }
604   template<typename _Tp, typename = __void_t<>>
605     struct __is_executor_impl : false_type
606     { };
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     >>;
624   template<typename _Tp>
625     struct __is_executor_impl<_Tp, decltype(__executor_reqs<_Tp>())>
626     : true_type
627     { };
629   template<typename _Tp>
630     struct is_executor : __is_executor_impl<_Tp>
631     { };
633   template<typename _Tp>
634     constexpr bool is_executor_v = is_executor<_Tp>::value;
636   template<typename _Tp, typename _Executor, typename = __void_t<>>
637     struct __uses_executor_impl : false_type
638     { };
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     { };
646   template<typename _Tp, typename _Executor>
647     struct uses_executor : __uses_executor_impl<_Tp, _Executor>::type
648     { };
650   template<typename _Tp, typename _Executor>
651     constexpr bool uses_executor_v = uses_executor<_Tp, _Executor>::value;
653   template<typename _Tp, typename _Executor>
654     class executor_binder
655     {
656       struct __use_exec { };
658     public:
659       // types:
661       typedef _Tp target_type;
662       typedef _Executor executor_type;
664       // construct / copy / destroy:
666       executor_binder(_Tp __t, const _Executor& __ex)
667       : executor_binder(__use_exec{}, std::move(__t), __ex)
668       { }
670       executor_binder(const executor_binder&) = default;
671       executor_binder(executor_binder&&) = default;
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         { }
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         { }
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         { }
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         { }
696       ~executor_binder();
698       // executor binder access:
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; }
704       // executor binder invocation:
706       template<class... _Args>
707         result_of_t<_Tp&(_Args&&...)>
708         operator()(_Args&&... __args)
709         { return std::__invoke(get(), std::forward<_Args>(__args)...); }
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)...); }
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>>;
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         { }
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         { }
736       _Executor _M_ex;
737       _Tp       _M_target;
738     };
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>;
745     public:
746       using completion_handler_type =
747         executor_binder<typename __inner::completion_handler_type, _Executor>;
749       using return_type = typename __inner::return_type;
751       explicit
752       async_result(completion_handler_type& __h)
753       : _M_target(__h.get()) { }
755       async_result(const async_result&) = delete;
756       async_result& operator=(const async_result&) = delete;
758       return_type get() { return _M_target.get(); }
760     private:
761       __inner _M_target;
762     };
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;
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     };
775   template<typename _Tp, typename _Executor, typename _Executor1>
776     struct associated_executor<executor_binder<_Tp, _Executor>, _Executor1>
777     {
778       typedef _Executor type;
780       static type
781       get(const executor_binder<_Tp, _Executor>& __b,
782           const _Executor1& = _Executor1()) noexcept
783       { return __b.get_executor(); }
784     };
786   template<typename _Executor>
787     class executor_work_guard
788     {
789     public:
790       // types:
792       typedef _Executor executor_type;
794       // construct / copy / destroy:
796       explicit
797       executor_work_guard(const executor_type& __ex) noexcept
798       : _M_ex(__ex), _M_owns(true)
799       { _M_ex.on_work_started(); }
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       }
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; }
812       executor_work_guard& operator=(const executor_work_guard&) = delete;
814       ~executor_work_guard()
815       {
816         if (_M_owns)
817           _M_ex.on_work_finished();
818       }
820       // executor work guard observers:
822       executor_type get_executor() const noexcept { return _M_ex; }
824       bool owns_work() const noexcept { return _M_owns; }
826       // executor work guard modifiers:
828       void reset() noexcept
829       {
830         if (_M_owns)
831           _M_ex.on_work_finished();
832         _M_owns = false;
833       }
835     private:
836       _Executor _M_ex;
837       bool      _M_owns;
838     };
841   class system_context : public execution_context
842   {
843   public:
844     // types:
846     typedef system_executor executor_type;
848     // construct / copy / destroy:
850     system_context() = default;
851     system_context(const system_context&) = delete;
852     system_context& operator=(const system_context&) = delete;
854     ~system_context()
855     {
856       stop();
857       join();
858     }
860     // system_context operations:
862     executor_type get_executor() noexcept;
864     void stop()
865     {
866       lock_guard<mutex> __lock(_M_mtx);
867       _M_stopped = true;
868       _M_cv.notify_all();
869     }
871     bool stopped() const noexcept
872     {
873       lock_guard<mutex> __lock(_M_mtx);
874       return _M_stopped;
875     }
877     void join()
878     {
879       _M_thread.join();
880     }
882   private:
883     friend system_executor;
885     struct __tag { };
886     system_context(__tag) { }
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;
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     }
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     }
925     static system_context&
926     _S_get() noexcept
927     {
928       static system_context __sc(__tag{});
929       return __sc;
930     }
931   };
933   class system_executor
934   {
935   public:
936     // executor operations:
938     system_executor() { }
940     system_context&
941     context() const noexcept { return system_context::_S_get(); }
943     void on_work_started() const noexcept { }
944     void on_work_finished() const noexcept { }
946     template<typename _Func, typename _ProtoAlloc>
947       void
948       dispatch(_Func&& __f, const _ProtoAlloc& __a) const
949       { decay_t<_Func>{std::forward<_Func>(__f)}(); }
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       }
958     template<typename _Func, typename _ProtoAlloc>
959       void
960       defer(_Func&& __f, const _ProtoAlloc& __a) const
961       { post(std::forward<_Func>(__f), __a); }
962   };
964   inline system_executor
965   system_context::get_executor() noexcept
966   { return {}; }
968   class bad_executor : public std::exception
969   {
970     virtual const char* what() const noexcept { return "bad executor"; }
971   };
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   }
982   class executor
983   {
984   public:
985     // construct / copy / destroy:
987     executor() noexcept = default;
989     executor(nullptr_t) noexcept { }
990     executor(const executor&) noexcept = default;
991     executor(executor&&) noexcept = default;
993     template<typename _Executor>
994       executor(_Executor __e)
995       : _M_target(_M_create(std::move(__e)))
996       { }
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       { }
1003     executor& operator=(const executor&) noexcept = default;
1004     executor& operator=(executor&&) noexcept = default;
1006     executor&
1007     operator=(nullptr_t) noexcept
1008     {
1009       _M_target = nullptr;
1010       return *this;
1011     }
1013     template<typename _Executor>
1014       executor&
1015       operator=(_Executor __e)
1016       {
1017         executor(std::move(__e)).swap(*this);
1018         return *this;
1019       }
1021     ~executor() = default;
1023     // executor modifiers:
1025     void
1026     swap(executor& __other) noexcept
1027     { _M_target.swap(__other._M_target); }
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); }
1034     // executor operations:
1036     execution_context&
1037     context() const noexcept
1038     {
1039       __glibcxx_assert( _M_target );
1040       return _M_target->context();
1041     }
1043     void
1044     on_work_started() const noexcept
1045     {
1046       __glibcxx_assert( _M_target );
1047       return _M_target->on_work_started();
1048     }
1050     void
1051     on_work_finished() const noexcept
1052     {
1053       __glibcxx_assert( _M_target );
1054       return _M_target->on_work_finished();
1055     }
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       }
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       }
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       }
1087     // executor capacity:
1089     explicit operator bool() const noexcept
1090     { return static_cast<bool>(_M_target); }
1092     // executor target access:
1094 #if __cpp_rtti
1095     const type_info&
1096     target_type() const noexcept
1097     { return _M_target ? _M_target->target_type() : typeid(void); }
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       }
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
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     };
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) { }
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()); }
1157 #if __cpp_rtti
1158         virtual const type_info&
1159         target_type() const
1160         { return typeid(_Ex); }
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         }
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         }
1178         virtual const void*
1179         _M_get_executor() const noexcept
1180         { return std::addressof(_M_ex()); }
1181 #endif
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       };
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       }
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     }
1210     shared_ptr<_Tgt> _M_target;
1211   };
1213   template<> struct is_executor<executor> : true_type { };
1215   /// executor comparisons
1216   inline bool
1217   operator==(const executor& __e, nullptr_t) noexcept
1218   { return !__e; }
1220   /// Swap two executor objects.
1221   inline void swap(executor& __a, executor& __b) noexcept { __a.swap(__b); }
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       { }
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       }
1239       _CompletionHandler _M_h;
1240       decltype(net::make_work_guard(_M_h)) _M_w;
1241     };
1243   template<typename _CompletionHandler>
1244     inline __dispatcher<_CompletionHandler>
1245     __make_dispatcher(_CompletionHandler& __h)
1246     { return __dispatcher<_CompletionHandler>{__h}; }
1250   // dispatch:
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     }
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     }
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     }
1286   // post:
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     }
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     }
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     }
1321   // defer:
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     }
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     }
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     }
1357   template<typename _Executor>
1358     class strand
1359     {
1360     public:
1361       // types:
1363       typedef _Executor inner_executor_type;
1365       // construct / copy / destroy:
1367       strand(); // TODO make state
1369       explicit strand(_Executor __ex) : _M_inner_ex(__ex) { } // TODO make state
1371       template<typename _Alloc>
1372         strand(allocator_arg_t, const _Alloc& __a, _Executor __ex)
1373         : _M_inner_ex(__ex) { } // TODO make state
1375       strand(const strand& __other) noexcept
1376       : _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }
1378       strand(strand&& __other) noexcept
1379       : _M_state(std::move(__other._M_state)),
1380         _M_inner_ex(std::move(__other._M_inner_ex)) { }
1382       template<typename _OtherExecutor>
1383         strand(const strand<_OtherExecutor>& __other) noexcept
1384         : _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }
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)) { }
1391       strand&
1392       operator=(const strand& __other) noexcept
1393       {
1394         static_assert(is_copy_assignable<_Executor>::value,
1395                       "inner executor type must be CopyAssignable");
1397         // TODO lock __other
1398         // TODO copy state
1399         _M_inner_ex = __other._M_inner_ex;
1400         return *this;
1401       }
1403       strand&
1404       operator=(strand&& __other) noexcept
1405       {
1406         static_assert(is_move_assignable<_Executor>::value,
1407                       "inner executor type must be MoveAssignable");
1409         // TODO move state
1410         _M_inner_ex = std::move(__other._M_inner_ex);
1411         return *this;
1412       }
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");
1421           // TODO lock __other
1422           // TODO copy state
1423           _M_inner_ex = __other._M_inner_ex;
1424           return *this;
1425         }
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");
1434           // TODO move state
1435           _M_inner_ex = std::move(__other._M_inner_ex);
1436           return *this;
1437         }
1439       ~strand()
1440       {
1441         // the task queue outlives this object if non-empty
1442         // TODO create circular ref in queue?
1443       }
1445       // strand operations:
1447       inner_executor_type
1448       get_inner_executor() const noexcept
1449       { return _M_inner_ex; }
1451       bool
1452       running_in_this_thread() const noexcept
1453       { return std::this_thread::get_id() == _M_state->_M_running_on; }
1455       execution_context&
1456       context() const noexcept
1457       { return _M_inner_ex.context(); }
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(); }
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         }
1472       template<typename _Func, typename _Alloc>
1473         void
1474         post(_Func&& __f, const _Alloc& __a) const; // TODO
1476       template<typename _Func, typename _Alloc>
1477         void
1478         defer(_Func&& __f, const _Alloc& __a) const
1479         { post(std::forward<_Func>(__f), __a); }
1481     private:
1482       friend bool
1483       operator==(const strand& __a, const strand& __b)
1484       { return __a._M_state == __b._M_state; }
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     };
1495 #if defined(_GLIBCXX_HAS_GTHREADS) && defined(_GLIBCXX_USE_C99_STDINT_TR1)
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     };
1504   template<typename _ProtoAllocator = allocator<void>>
1505     class use_future_t
1506     {
1507     public:
1508       // use_future_t types:
1509       typedef _ProtoAllocator allocator_type;
1511       // use_future_t members:
1512       constexpr use_future_t() noexcept : _M_alloc() { }
1514       explicit
1515       use_future_t(const _ProtoAllocator& __a) noexcept : _M_alloc(__a) { }
1517       template<class _OtherAllocator>
1518         use_future_t<_OtherAllocator>
1519         rebind(const _OtherAllocator& __a) const noexcept
1520         { return use_future_t<_OtherAllocator>(__a); }
1522       allocator_type get_allocator() const noexcept { return _M_alloc; }
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         }
1532     private:
1533       _ProtoAllocator _M_alloc;
1534     };
1536   constexpr use_future_t<> use_future = use_future_t<>();
1538   template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
1539     class async_result<__use_future_ct<_Func, _Alloc>, _Res(_Args...)>;
1541   template<typename _Result, typename _Executor>
1542     struct __use_future_ex;
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         { }
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       }
1572       using __result = result_of_t<_Func(decay_t<_Args>...)>;
1574       future<__result> get_future() { return _M_promise.get_future(); }
1576     private:
1577       template<typename _Result, typename _Executor>
1578         friend struct __use_future_ex;
1580       _Func _M_f;
1581       mutable promise<__result> _M_promise;
1582     };
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>;
1592       explicit
1593       async_result(completion_handler_type& __h)
1594       : _M_future(__h.get_future())
1595       { }
1597       async_result(const async_result&) = delete;
1598       async_result& operator=(const async_result&) = delete;
1600       return_type get() { return std::move(_M_future); }
1602     private:
1603       return_type _M_future;
1604     };
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       { }
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         }
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         }
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         }
1668     private:
1669       tuple<promise<_Result>&, _Executor> _M_t;
1670     };
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...>;
1678       using type = __use_future_ex<typename __handler::__result, _Executor>;
1680       static type
1681       get(const __handler& __h, const _Executor& __ex)
1682       { return { __h, __ex }; }
1683     };
1685 #if 0
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 { };
1694       template<typename... _Args>
1695         struct __is_error_result<error_code, _Args...> : true_type { };
1697       template<typename... _Args>
1698         struct __is_error_result<exception_ptr, _Args...> : true_type { };
1700       static exception_ptr
1701       _S_exptr(exception_ptr& __ex)
1702       { return std::move(__ex); }
1704       static exception_ptr
1705       _S_exptr(const error_code& __ec)
1706       { return make_exception_ptr(system_error(__ec)); }
1708       template<bool _IsError, typename... _UArgs>
1709         struct _Type;
1711       // N == 0
1712       template<bool _IsError>
1713         struct _Type<_IsError>
1714         {
1715           std::promise<void> _M_promise;
1717           void
1718           operator()()
1719           {
1720             _M_promise.set_value();
1721           }
1722         };
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;
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         };
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;
1747           template<typename _Arg0>
1748             void
1749             operator()(_Arg0&& __a0)
1750             {
1751               _M_promise.set_value(std::forward<_Arg0>(__a0));
1752             }
1753         };
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;
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         };
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");
1778           std::promise<tuple<_UArgs...>> _M_promise;
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         };
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");
1795           std::promise<tuple<_UArgs...>> _M_promise;
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         };
1809     public:
1810       using type =
1811         _Type<__is_error_result<_Args...>::value, decay_t<_Args>...>;
1812     };
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;
1821       using return_type = void; // XXX TODO ???;
1823       explicit
1824       async_result(completion_handler_type& __h) : _M_handler(__h) { }
1826       auto get() { return _M_handler._M_provider.get_future(); }
1828       async_result(const async_result&) = delete;
1829       async_result& operator=(const async_result&) = delete;
1831       return_type get() { return _M_handler._M_promise.get_future(); }
1833     private:
1834       completion_handler_type& _M_handler;
1835     };
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)
1844 #endif
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>;
1854       explicit
1855       async_result(completion_handler_type& __h)
1856       : _M_future(__h.get_future()) { }
1858       async_result(const async_result&) = delete;
1859       async_result& operator=(const async_result&) = delete;
1861       return_type get() { return std::move(_M_future); }
1863     private:
1864       return_type _M_future;
1865     };
1867 #endif
1869   /// @}
1871 } // namespace v1
1872 } // namespace net
1873 } // namespace experimental
1875   template<typename _Alloc>
1876     struct uses_allocator<experimental::net::executor, _Alloc>
1877     : true_type {};
1879 _GLIBCXX_END_NAMESPACE_VERSION
1880 } // namespace std
1882 #endif // C++14
1884 #endif // _GLIBCXX_EXPERIMENTAL_EXECUTOR