You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2015 lines
54KB

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