executor 51 KB

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