executor 55 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049
  1. // <experimental/executor> -*- C++ -*-
  2. // Copyright (C) 2015-2021 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. using completion_handler_type = _CompletionToken;
  291. using return_type = void;
  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. #if defined(_GLIBCXX_HAS_GTHREADS)
  396. using mutex_type = std::mutex;
  397. #else
  398. struct mutex_type
  399. {
  400. void lock() const { }
  401. void unlock() const { }
  402. };
  403. #endif
  404. mutable mutex_type _M_mutex;
  405. // Sorted in order of beginning of service object lifetime.
  406. std::list<_ServicePtr> _M_services;
  407. template<typename _Service, typename... _Args>
  408. service*
  409. _M_add_svc(_Args&&... __args)
  410. {
  411. _M_services.push_back(
  412. _ServicePtr{new _Service{*this, std::forward<_Args>(__args)...}} );
  413. return _M_services.back()._M_ptr.get();
  414. }
  415. using __key_type = void(*)();
  416. template<typename _Key>
  417. static __key_type
  418. _S_key() { return reinterpret_cast<__key_type>(&_S_key<_Key>); }
  419. std::unordered_map<__key_type, service*> _M_keys;
  420. template<typename _Service>
  421. friend typename _Service::key_type&
  422. use_service(execution_context&);
  423. template<typename _Service, typename... _Args>
  424. friend _Service&
  425. make_service(execution_context&, _Args&&...);
  426. template<typename _Service>
  427. friend bool
  428. has_service(const execution_context&) noexcept;
  429. };
  430. // service access:
  431. template<typename _Service>
  432. typename _Service::key_type&
  433. use_service(execution_context& __ctx)
  434. {
  435. using _Key = typename _Service::key_type;
  436. static_assert(is_base_of<execution_context::service, _Key>::value,
  437. "a service type must derive from execution_context::service");
  438. static_assert(is_base_of<_Key, _Service>::value,
  439. "a service type must match or derive from its key_type");
  440. auto __key = execution_context::_S_key<_Key>();
  441. lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
  442. auto& __svc = __ctx._M_keys[__key];
  443. if (__svc == nullptr)
  444. {
  445. __try {
  446. __svc = __ctx._M_add_svc<_Service>();
  447. } __catch(...) {
  448. __ctx._M_keys.erase(__key);
  449. __throw_exception_again;
  450. }
  451. }
  452. return static_cast<_Key&>(*__svc);
  453. }
  454. template<typename _Service, typename... _Args>
  455. _Service&
  456. make_service(execution_context& __ctx, _Args&&... __args)
  457. {
  458. using _Key = typename _Service::key_type;
  459. static_assert(is_base_of<execution_context::service, _Key>::value,
  460. "a service type must derive from execution_context::service");
  461. static_assert(is_base_of<_Key, _Service>::value,
  462. "a service type must match or derive from its key_type");
  463. auto __key = execution_context::_S_key<_Key>();
  464. lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
  465. auto& __svc = __ctx._M_keys[__key];
  466. if (__svc != nullptr)
  467. throw service_already_exists();
  468. __try {
  469. __svc = __ctx._M_add_svc<_Service>(std::forward<_Args>(__args)...);
  470. } __catch(...) {
  471. __ctx._M_keys.erase(__key);
  472. __throw_exception_again;
  473. }
  474. return static_cast<_Service&>(*__svc);
  475. }
  476. template<typename _Service>
  477. inline bool
  478. has_service(const execution_context& __ctx) noexcept
  479. {
  480. using _Key = typename _Service::key_type;
  481. static_assert(is_base_of<execution_context::service, _Key>::value,
  482. "a service type must derive from execution_context::service");
  483. static_assert(is_base_of<_Key, _Service>::value,
  484. "a service type must match or derive from its key_type");
  485. lock_guard<execution_context::mutex_type> __lock(__ctx._M_mutex);
  486. return __ctx._M_keys.count(execution_context::_S_key<_Key>());
  487. }
  488. template<typename _Tp, typename = __void_t<>>
  489. struct __is_executor_impl : false_type
  490. { };
  491. // Check Executor requirements.
  492. template<typename _Tp, typename _Up = remove_const_t<_Tp>>
  493. auto
  494. __executor_reqs(_Up* __x = 0, const _Up* __cx = 0, void(*__f)() = 0,
  495. const allocator<int>& __a = {})
  496. -> enable_if_t<__is_value_constructible<_Tp>::value, __void_t<
  497. decltype(*__cx == *__cx),
  498. decltype(*__cx != *__cx),
  499. decltype(__x->context()),
  500. decltype(__x->on_work_started()),
  501. decltype(__x->on_work_finished()),
  502. decltype(__x->dispatch(std::move(__f), __a)),
  503. decltype(__x->post(std::move(__f), __a)),
  504. decltype(__x->defer(std::move(__f), __a))
  505. >>;
  506. template<typename _Tp>
  507. struct __is_executor_impl<_Tp, decltype(__executor_reqs<_Tp>())>
  508. : true_type
  509. { };
  510. template<typename _Tp>
  511. struct is_executor : __is_executor_impl<_Tp>
  512. { };
  513. template<typename _Tp>
  514. constexpr bool is_executor_v = is_executor<_Tp>::value;
  515. template<typename _Tp, typename _Executor, typename = __void_t<>>
  516. struct __uses_executor_impl : false_type
  517. { };
  518. template<typename _Tp, typename _Executor>
  519. struct __uses_executor_impl<_Tp, _Executor,
  520. __void_t<typename _Tp::executor_type>>
  521. : is_convertible<_Executor, typename _Tp::executor_type>
  522. { };
  523. template<typename _Tp, typename _Executor>
  524. struct uses_executor : __uses_executor_impl<_Tp, _Executor>::type
  525. { };
  526. template<typename _Tp, typename _Executor>
  527. constexpr bool uses_executor_v = uses_executor<_Tp, _Executor>::value;
  528. template<typename _Tp, typename _Executor>
  529. class executor_binder
  530. {
  531. struct __use_exec { };
  532. public:
  533. // types:
  534. using target_type = _Tp;
  535. using executor_type = _Executor;
  536. // construct / copy / destroy:
  537. executor_binder(_Tp __t, const _Executor& __ex)
  538. : executor_binder(__use_exec{}, std::move(__t), __ex)
  539. { }
  540. executor_binder(const executor_binder&) = default;
  541. executor_binder(executor_binder&&) = default;
  542. template<typename _Up, typename _OtherExecutor>
  543. executor_binder(const executor_binder<_Up, _OtherExecutor>& __other)
  544. : executor_binder(__use_exec{}, __other.get(), __other.get_executor())
  545. { }
  546. template<typename _Up, typename _OtherExecutor>
  547. executor_binder(executor_binder<_Up, _OtherExecutor>&& __other)
  548. : executor_binder(__use_exec{}, std::move(__other.get()),
  549. __other.get_executor())
  550. { }
  551. template<typename _Up, typename _OtherExecutor>
  552. executor_binder(executor_arg_t, const _Executor& __ex,
  553. const executor_binder<_Up, _OtherExecutor>& __other)
  554. : executor_binder(__use_exec{}, __other.get(), __ex)
  555. { }
  556. template<typename _Up, typename _OtherExecutor>
  557. executor_binder(executor_arg_t, const _Executor& __ex,
  558. executor_binder<_Up, _OtherExecutor>&& __other)
  559. : executor_binder(__use_exec{}, std::move(__other.get()), __ex)
  560. { }
  561. ~executor_binder();
  562. // executor binder access:
  563. _Tp& get() noexcept { return _M_target; }
  564. const _Tp& get() const noexcept { return _M_target; }
  565. executor_type get_executor() const noexcept { return _M_ex; }
  566. // executor binder invocation:
  567. template<class... _Args>
  568. result_of_t<_Tp&(_Args&&...)>
  569. operator()(_Args&&... __args)
  570. { return std::__invoke(get(), std::forward<_Args>(__args)...); }
  571. template<class... _Args>
  572. result_of_t<const _Tp&(_Args&&...)>
  573. operator()(_Args&&... __args) const
  574. { return std::__invoke(get(), std::forward<_Args>(__args)...); }
  575. private:
  576. template<typename _Up>
  577. using __use_exec_cond
  578. = __and_<uses_executor<_Tp, _Executor>,
  579. is_constructible<_Tp, executor_arg_t, _Executor, _Up>>;
  580. template<typename _Up, typename _Exec, typename =
  581. enable_if_t<__use_exec_cond<_Up>::value>>
  582. executor_binder(__use_exec, _Up&& __u, _Exec&& __ex)
  583. : _M_ex(std::forward<_Exec>(__ex)),
  584. _M_target(executor_arg, _M_ex, std::forward<_Up>(__u))
  585. { }
  586. template<typename _Up, typename _Exec, typename =
  587. enable_if_t<!__use_exec_cond<_Up>::value>>
  588. executor_binder(__use_exec, _Up&& __u, const _Exec& __ex)
  589. : _M_ex(std::forward<_Exec>(__ex)),
  590. _M_target(std::forward<_Up>(__u))
  591. { }
  592. _Executor _M_ex;
  593. _Tp _M_target;
  594. };
  595. template<typename _Tp, typename _Executor, typename _Signature>
  596. class async_result<executor_binder<_Tp, _Executor>, _Signature>
  597. {
  598. using __inner = async_result<_Tp, _Signature>;
  599. public:
  600. using completion_handler_type =
  601. executor_binder<typename __inner::completion_handler_type, _Executor>;
  602. using return_type = typename __inner::return_type;
  603. explicit
  604. async_result(completion_handler_type& __h)
  605. : _M_target(__h.get()) { }
  606. async_result(const async_result&) = delete;
  607. async_result& operator=(const async_result&) = delete;
  608. return_type get() { return _M_target.get(); }
  609. private:
  610. __inner _M_target;
  611. };
  612. template<typename _Tp, typename _Executor, typename _ProtoAlloc>
  613. struct associated_allocator<executor_binder<_Tp, _Executor>, _ProtoAlloc>
  614. {
  615. using type = associated_allocator_t<_Tp, _ProtoAlloc>;
  616. static type
  617. get(const executor_binder<_Tp, _Executor>& __b,
  618. const _ProtoAlloc& __a = _ProtoAlloc()) noexcept
  619. { return associated_allocator<_Tp, _ProtoAlloc>::get(__b.get(), __a); }
  620. };
  621. template<typename _Tp, typename _Executor, typename _Executor1>
  622. struct associated_executor<executor_binder<_Tp, _Executor>, _Executor1>
  623. {
  624. using type = _Executor;
  625. static type
  626. get(const executor_binder<_Tp, _Executor>& __b,
  627. const _Executor1& = _Executor1()) noexcept
  628. { return __b.get_executor(); }
  629. };
  630. template<typename _Executor>
  631. class executor_work_guard
  632. {
  633. public:
  634. // types:
  635. using executor_type = _Executor;
  636. // construct / copy / destroy:
  637. explicit
  638. executor_work_guard(const executor_type& __ex) noexcept
  639. : _M_ex(__ex), _M_owns(true)
  640. { _M_ex.on_work_started(); }
  641. executor_work_guard(const executor_work_guard& __other) noexcept
  642. : _M_ex(__other._M_ex), _M_owns(__other._M_owns)
  643. {
  644. if (_M_owns)
  645. _M_ex.on_work_started();
  646. }
  647. executor_work_guard(executor_work_guard&& __other) noexcept
  648. : _M_ex(__other._M_ex), _M_owns(__other._M_owns)
  649. { __other._M_owns = false; }
  650. executor_work_guard& operator=(const executor_work_guard&) = delete;
  651. ~executor_work_guard()
  652. {
  653. if (_M_owns)
  654. _M_ex.on_work_finished();
  655. }
  656. // executor work guard observers:
  657. executor_type get_executor() const noexcept { return _M_ex; }
  658. bool owns_work() const noexcept { return _M_owns; }
  659. // executor work guard modifiers:
  660. void reset() noexcept
  661. {
  662. if (_M_owns)
  663. _M_ex.on_work_finished();
  664. _M_owns = false;
  665. }
  666. private:
  667. _Executor _M_ex;
  668. bool _M_owns;
  669. };
  670. class system_context : public execution_context
  671. {
  672. public:
  673. // types:
  674. using executor_type = system_executor;
  675. // construct / copy / destroy:
  676. system_context() = delete;
  677. system_context(const system_context&) = delete;
  678. system_context& operator=(const system_context&) = delete;
  679. ~system_context()
  680. {
  681. stop();
  682. join();
  683. }
  684. // system_context operations:
  685. executor_type get_executor() noexcept;
  686. void stop()
  687. {
  688. lock_guard<mutex_type> __lock(_M_mtx);
  689. _M_stopped = true;
  690. _M_cv.notify_all();
  691. }
  692. bool stopped() const noexcept
  693. {
  694. lock_guard<mutex_type> __lock(_M_mtx);
  695. return _M_stopped;
  696. }
  697. void join()
  698. {
  699. if (_M_thread.joinable())
  700. _M_thread.join();
  701. }
  702. private:
  703. friend system_executor;
  704. struct __tag { explicit __tag() = default; };
  705. system_context(__tag) { }
  706. #ifndef _GLIBCXX_HAS_GTHREADS
  707. struct thread
  708. {
  709. bool joinable() const { return false; }
  710. void join() { }
  711. };
  712. struct condition_variable
  713. {
  714. void notify_all() { }
  715. };
  716. #endif
  717. thread _M_thread;
  718. mutable mutex_type _M_mtx; // XXX can we reuse base's _M_mutex?
  719. condition_variable _M_cv;
  720. queue<function<void()>> _M_tasks;
  721. bool _M_stopped = false;
  722. #ifdef _GLIBCXX_HAS_GTHREADS
  723. void
  724. _M_run()
  725. {
  726. while (true)
  727. {
  728. function<void()> __f;
  729. {
  730. unique_lock<mutex_type> __lock(_M_mtx);
  731. _M_cv.wait(__lock,
  732. [this]{ return _M_stopped || !_M_tasks.empty(); });
  733. if (_M_stopped)
  734. return;
  735. __f = std::move(_M_tasks.front());
  736. _M_tasks.pop();
  737. }
  738. __f();
  739. }
  740. }
  741. #endif
  742. void
  743. _M_post(std::function<void()> __f __attribute__((__unused__)))
  744. {
  745. lock_guard<mutex_type> __lock(_M_mtx);
  746. if (_M_stopped)
  747. return;
  748. #ifdef _GLIBCXX_HAS_GTHREADS
  749. if (!_M_thread.joinable())
  750. _M_thread = std::thread(&system_context::_M_run, this);
  751. _M_tasks.push(std::move(__f)); // XXX allocator not used
  752. _M_cv.notify_one();
  753. #else
  754. __throw_system_error(EOPNOTSUPP);
  755. #endif
  756. }
  757. static system_context&
  758. _S_get() noexcept
  759. {
  760. static system_context __sc(__tag{});
  761. return __sc;
  762. }
  763. };
  764. class system_executor
  765. {
  766. public:
  767. // executor operations:
  768. system_executor() { }
  769. system_context&
  770. context() const noexcept { return system_context::_S_get(); }
  771. void on_work_started() const noexcept { }
  772. void on_work_finished() const noexcept { }
  773. template<typename _Func, typename _ProtoAlloc>
  774. void
  775. dispatch(_Func&& __f, const _ProtoAlloc& __a) const
  776. { decay_t<_Func>{std::forward<_Func>(__f)}(); }
  777. template<typename _Func, typename _ProtoAlloc>
  778. void
  779. post(_Func&& __f, const _ProtoAlloc&) const // XXX allocator not used
  780. {
  781. system_context::_S_get()._M_post(std::forward<_Func>(__f));
  782. }
  783. template<typename _Func, typename _ProtoAlloc>
  784. void
  785. defer(_Func&& __f, const _ProtoAlloc& __a) const
  786. { post(std::forward<_Func>(__f), __a); }
  787. };
  788. inline system_executor
  789. system_context::get_executor() noexcept
  790. { return {}; }
  791. class bad_executor : public std::exception
  792. {
  793. virtual const char* what() const noexcept { return "bad executor"; }
  794. };
  795. inline void __throw_bad_executor() // TODO make non-inline
  796. {
  797. #if __cpp_exceptions
  798. throw bad_executor();
  799. #else
  800. __builtin_abort();
  801. #endif
  802. }
  803. class executor
  804. {
  805. public:
  806. // construct / copy / destroy:
  807. executor() noexcept = default;
  808. executor(nullptr_t) noexcept { }
  809. executor(const executor&) noexcept = default;
  810. executor(executor&&) noexcept = default;
  811. template<typename _Executor>
  812. executor(_Executor __e)
  813. : _M_target(make_shared<_Tgt1<_Executor>>(std::move(__e)))
  814. { }
  815. template<typename _Executor, typename _ProtoAlloc>
  816. executor(allocator_arg_t, const _ProtoAlloc& __a, _Executor __e)
  817. : _M_target(allocate_shared<_Tgt2<_Executor, _ProtoAlloc>>(__a,
  818. std::move(__e), __a))
  819. { }
  820. executor& operator=(const executor&) noexcept = default;
  821. executor& operator=(executor&&) noexcept = default;
  822. executor&
  823. operator=(nullptr_t) noexcept
  824. {
  825. _M_target = nullptr;
  826. return *this;
  827. }
  828. template<typename _Executor>
  829. executor&
  830. operator=(_Executor __e)
  831. {
  832. executor(std::move(__e)).swap(*this);
  833. return *this;
  834. }
  835. ~executor() = default;
  836. // executor modifiers:
  837. void
  838. swap(executor& __other) noexcept
  839. { _M_target.swap(__other._M_target); }
  840. template<typename _Executor, typename _Alloc>
  841. void
  842. assign(_Executor __e, const _Alloc& __a)
  843. { executor(allocator_arg, __a, std::move(__e)).swap(*this); }
  844. // executor operations:
  845. execution_context&
  846. context() const noexcept
  847. {
  848. __glibcxx_assert( _M_target );
  849. return _M_target->context();
  850. }
  851. void
  852. on_work_started() const noexcept
  853. {
  854. __glibcxx_assert( _M_target );
  855. return _M_target->on_work_started();
  856. }
  857. void
  858. on_work_finished() const noexcept
  859. {
  860. __glibcxx_assert( _M_target );
  861. return _M_target->on_work_finished();
  862. }
  863. template<typename _Func, typename _Alloc>
  864. void
  865. dispatch(_Func&& __f, const _Alloc& __a) const
  866. {
  867. if (!_M_target)
  868. __throw_bad_executor();
  869. // _M_target->dispatch({allocator_arg, __a, std::forward<_Func>(__f)});
  870. _M_target->dispatch(std::forward<_Func>(__f));
  871. }
  872. template<typename _Func, typename _Alloc>
  873. void
  874. post(_Func&& __f, const _Alloc& __a) const
  875. {
  876. if (!_M_target)
  877. __throw_bad_executor();
  878. // _M_target->post({allocator_arg, __a, std::forward<_Func>(__f)});
  879. _M_target->post(std::forward<_Func>(__f));
  880. }
  881. template<typename _Func, typename _Alloc>
  882. void
  883. defer(_Func&& __f, const _Alloc& __a) const
  884. {
  885. if (!_M_target)
  886. __throw_bad_executor();
  887. // _M_target->defer({allocator_arg, __a, std::forward<_Func>(__f)});
  888. _M_target->defer(std::forward<_Func>(__f));
  889. }
  890. // executor capacity:
  891. explicit operator bool() const noexcept
  892. { return static_cast<bool>(_M_target); }
  893. // executor target access:
  894. #if __cpp_rtti
  895. const type_info&
  896. target_type() const noexcept
  897. {
  898. if (_M_target)
  899. return *static_cast<const type_info*>(_M_target->target_type());
  900. return typeid(void);
  901. }
  902. #endif
  903. template<typename _Executor>
  904. _Executor*
  905. target() noexcept
  906. {
  907. void* __p = nullptr;
  908. if (_M_target)
  909. {
  910. if (_M_target->_M_func == &_Tgt1<remove_cv_t<_Executor>>::_S_func)
  911. __p = _M_target->_M_func(_M_target.get(), nullptr);
  912. #if __cpp_rtti
  913. else
  914. __p = _M_target->target(&typeid(_Executor));
  915. #endif
  916. }
  917. return static_cast<_Executor*>(__p);
  918. }
  919. template<typename _Executor>
  920. const _Executor*
  921. target() const noexcept
  922. {
  923. const void* __p = nullptr;
  924. if (_M_target)
  925. {
  926. if (_M_target->_M_func == &_Tgt1<remove_cv_t<_Executor>>::_S_func)
  927. return (_Executor*)_M_target->_M_func(_M_target.get(), nullptr);
  928. #if __cpp_rtti
  929. else
  930. __p = _M_target->target(&typeid(_Executor));
  931. #endif
  932. }
  933. return static_cast<const _Executor*>(__p);
  934. }
  935. private:
  936. struct _Tgt
  937. {
  938. virtual void on_work_started() const noexcept = 0;
  939. virtual void on_work_finished() const noexcept = 0;
  940. virtual execution_context& context() const noexcept = 0;
  941. virtual void dispatch(std::function<void()>) const = 0;
  942. virtual void post(std::function<void()>) const = 0;
  943. virtual void defer(std::function<void()>) const = 0;
  944. virtual const void* target_type() const noexcept = 0;
  945. virtual void* target(const void*) noexcept = 0;
  946. virtual bool _M_equals(_Tgt*) const noexcept = 0;
  947. using _Func = void* (_Tgt*, const _Tgt*);
  948. _Func* _M_func; // Provides access to target without RTTI
  949. };
  950. template<typename _Ex>
  951. struct _Tgt1 : _Tgt
  952. {
  953. explicit
  954. _Tgt1(_Ex&& __ex)
  955. : _M_ex(std::move(__ex))
  956. { this->_M_func = &_S_func; }
  957. void
  958. on_work_started() const noexcept override
  959. { _M_ex.on_work_started(); }
  960. void
  961. on_work_finished() const noexcept override
  962. { _M_ex.on_work_finished(); }
  963. execution_context&
  964. context() const noexcept override
  965. { return _M_ex.context(); }
  966. void
  967. dispatch(std::function<void()> __f) const override
  968. { _M_ex.dispatch(std::move(__f), allocator<void>()); }
  969. void
  970. post(std::function<void()> __f) const override
  971. { _M_ex.post(std::move(__f), allocator<void>()); }
  972. void
  973. defer(std::function<void()> __f) const override
  974. { _M_ex.defer(std::move(__f), allocator<void>()); }
  975. const void*
  976. target_type() const noexcept override
  977. {
  978. #if __cpp_rtti
  979. return &typeid(_Ex);
  980. #else
  981. return nullptr;
  982. #endif
  983. }
  984. void*
  985. target(const void* __ti) noexcept override
  986. {
  987. #if __cpp_rtti
  988. if (*static_cast<const type_info*>(__ti) == typeid(_Ex))
  989. return std::__addressof(_M_ex);
  990. #endif
  991. return nullptr;
  992. }
  993. bool
  994. _M_equals(_Tgt* __tgt) const noexcept override
  995. {
  996. #if __cpp_rtti
  997. if (const void* __p = __tgt->target(&typeid(_Ex)))
  998. return *static_cast<const _Ex*>(__p) == _M_ex;
  999. #endif
  1000. return false;
  1001. }
  1002. _Ex _M_ex [[__no_unique_address__]];
  1003. static void*
  1004. _S_func(_Tgt* __p, const _Tgt* __q) noexcept
  1005. {
  1006. auto& __ex = static_cast<_Tgt1*>(__p)->_M_ex;
  1007. if (__q)
  1008. {
  1009. if (__ex == static_cast<const _Tgt1*>(__q)->_M_ex)
  1010. return __p;
  1011. else
  1012. return nullptr;
  1013. }
  1014. else
  1015. return std::__addressof(__ex);
  1016. }
  1017. };
  1018. template<typename _Ex, typename _Alloc>
  1019. struct _Tgt2 : _Tgt1<_Ex>
  1020. {
  1021. explicit
  1022. _Tgt2(_Ex&& __ex, const _Alloc& __a)
  1023. : _Tgt1<_Ex>(std::move(__ex)), _M_alloc(__a) { }
  1024. void
  1025. dispatch(std::function<void()> __f) const override
  1026. { this->_M_ex.dispatch(std::move(__f), _M_alloc); }
  1027. void
  1028. post(std::function<void()> __f) const override
  1029. { this->_M_ex.post(std::move(__f), _M_alloc); }
  1030. void
  1031. defer(std::function<void()> __f) const override
  1032. { this->_M_ex.defer(std::move(__f), _M_alloc); }
  1033. _Alloc _M_alloc [[__no_unique_address__]];
  1034. };
  1035. // Partial specialization for std::allocator<T>.
  1036. // Don't store the allocator.
  1037. template<typename _Ex, typename _Tp>
  1038. struct _Tgt2<_Ex, std::allocator<_Tp>> : _Tgt1<_Ex>
  1039. { };
  1040. friend bool
  1041. operator==(const executor& __a, const executor& __b) noexcept
  1042. {
  1043. _Tgt* __ta = __a._M_target.get();
  1044. _Tgt* __tb = __b._M_target.get();
  1045. if (__ta == __tb)
  1046. return true;
  1047. if (!__ta || !__tb)
  1048. return false;
  1049. if (__ta->_M_func == __tb->_M_func)
  1050. return __ta->_M_func(__ta, __tb);
  1051. return __ta->_M_equals(__tb);
  1052. }
  1053. shared_ptr<_Tgt> _M_target;
  1054. };
  1055. template<> struct is_executor<executor> : true_type { };
  1056. /// executor comparisons
  1057. inline bool
  1058. operator==(const executor& __e, nullptr_t) noexcept
  1059. { return !__e; }
  1060. inline bool
  1061. operator==(nullptr_t, const executor& __e) noexcept
  1062. { return !__e; }
  1063. inline bool
  1064. operator!=(const executor& __a, const executor& __b) noexcept
  1065. { return !(__a == __b); }
  1066. inline bool
  1067. operator!=(const executor& __e, nullptr_t) noexcept
  1068. { return (bool)__e; }
  1069. inline bool
  1070. operator!=(nullptr_t, const executor& __e) noexcept
  1071. { return (bool)__e; }
  1072. /// Swap two executor objects.
  1073. inline void swap(executor& __a, executor& __b) noexcept { __a.swap(__b); }
  1074. template<typename _CompletionHandler>
  1075. struct __dispatcher
  1076. {
  1077. explicit
  1078. __dispatcher(_CompletionHandler& __h)
  1079. : _M_h(std::move(__h)), _M_w(net::make_work_guard(_M_h))
  1080. { }
  1081. void operator()()
  1082. {
  1083. auto __alloc = net::get_associated_allocator(_M_h);
  1084. _M_w.get_executor().dispatch(std::move(_M_h), __alloc);
  1085. _M_w.reset();
  1086. }
  1087. _CompletionHandler _M_h;
  1088. decltype(net::make_work_guard(_M_h)) _M_w;
  1089. };
  1090. template<typename _CompletionHandler>
  1091. inline __dispatcher<_CompletionHandler>
  1092. __make_dispatcher(_CompletionHandler& __h)
  1093. { return __dispatcher<_CompletionHandler>{__h}; }
  1094. // dispatch:
  1095. template<typename _CompletionToken>
  1096. inline __deduced_t<_CompletionToken, void()>
  1097. dispatch(_CompletionToken&& __token)
  1098. {
  1099. async_completion<_CompletionToken, void()> __cmpl{__token};
  1100. auto __ex = net::get_associated_executor(__cmpl.completion_handler);
  1101. auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
  1102. __ex.dispatch(std::move(__cmpl.completion_handler), __alloc);
  1103. return __cmpl.result.get();
  1104. }
  1105. template<typename _Executor, typename _CompletionToken>
  1106. inline
  1107. enable_if_t<is_executor<_Executor>::value,
  1108. __deduced_t<_CompletionToken, void()>>
  1109. dispatch(const _Executor& __ex, _CompletionToken&& __token)
  1110. {
  1111. async_completion<_CompletionToken, void()> __cmpl{__token};
  1112. auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
  1113. __ex.dispatch(net::__make_dispatcher(__cmpl.completion_handler),
  1114. __alloc);
  1115. return __cmpl.result.get();
  1116. }
  1117. template<typename _ExecutionContext, typename _CompletionToken>
  1118. inline
  1119. enable_if_t<__is_exec_context<_ExecutionContext>::value,
  1120. __deduced_t<_CompletionToken, void()>>
  1121. dispatch(_ExecutionContext& __ctx, _CompletionToken&& __token)
  1122. {
  1123. return net::dispatch(__ctx.get_executor(),
  1124. forward<_CompletionToken>(__token));
  1125. }
  1126. // post:
  1127. template<typename _CompletionToken>
  1128. inline __deduced_t<_CompletionToken, void()>
  1129. post(_CompletionToken&& __token)
  1130. {
  1131. async_completion<_CompletionToken, void()> __cmpl{__token};
  1132. auto __ex = net::get_associated_executor(__cmpl.completion_handler);
  1133. auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
  1134. __ex.post(std::move(__cmpl.completion_handler), __alloc);
  1135. return __cmpl.result.get();
  1136. }
  1137. template<typename _Executor, typename _CompletionToken>
  1138. inline
  1139. enable_if_t<is_executor<_Executor>::value,
  1140. __deduced_t<_CompletionToken, void()>>
  1141. post(const _Executor& __ex, _CompletionToken&& __token)
  1142. {
  1143. async_completion<_CompletionToken, void()> __cmpl{__token};
  1144. auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
  1145. __ex.post(net::__make_dispatcher(__cmpl.completion_handler), __alloc);
  1146. return __cmpl.result.get();
  1147. }
  1148. template<typename _ExecutionContext, typename _CompletionToken>
  1149. inline
  1150. enable_if_t<__is_exec_context<_ExecutionContext>::value,
  1151. __deduced_t<_CompletionToken, void()>>
  1152. post(_ExecutionContext& __ctx, _CompletionToken&& __token)
  1153. {
  1154. return net::post(__ctx.get_executor(),
  1155. forward<_CompletionToken>(__token));
  1156. }
  1157. // defer:
  1158. template<typename _CompletionToken>
  1159. inline __deduced_t<_CompletionToken, void()>
  1160. defer(_CompletionToken&& __token)
  1161. {
  1162. async_completion<_CompletionToken, void()> __cmpl{__token};
  1163. auto __ex = net::get_associated_executor(__cmpl.completion_handler);
  1164. auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
  1165. __ex.defer(std::move(__cmpl.completion_handler), __alloc);
  1166. return __cmpl.result.get();
  1167. }
  1168. template<typename _Executor, typename _CompletionToken>
  1169. inline
  1170. enable_if_t<is_executor<_Executor>::value,
  1171. __deduced_t<_CompletionToken, void()>>
  1172. defer(const _Executor& __ex, _CompletionToken&& __token)
  1173. {
  1174. async_completion<_CompletionToken, void()> __cmpl{__token};
  1175. auto __alloc = net::get_associated_allocator(__cmpl.completion_handler);
  1176. __ex.defer(net::__make_dispatcher(__cmpl.completion_handler), __alloc);
  1177. return __cmpl.result.get();
  1178. }
  1179. template<typename _ExecutionContext, typename _CompletionToken>
  1180. inline
  1181. enable_if_t<__is_exec_context<_ExecutionContext>::value,
  1182. __deduced_t<_CompletionToken, void()>>
  1183. defer(_ExecutionContext& __ctx, _CompletionToken&& __token)
  1184. {
  1185. return net::defer(__ctx.get_executor(),
  1186. forward<_CompletionToken>(__token));
  1187. }
  1188. template<typename _Executor>
  1189. class strand
  1190. {
  1191. public:
  1192. // types:
  1193. using inner_executor_type = _Executor;
  1194. // construct / copy / destroy:
  1195. strand(); // TODO make state
  1196. explicit strand(_Executor __ex) : _M_inner_ex(__ex) { } // TODO make state
  1197. template<typename _Alloc>
  1198. strand(allocator_arg_t, const _Alloc& __a, _Executor __ex)
  1199. : _M_inner_ex(__ex) { } // TODO make state
  1200. strand(const strand& __other) noexcept
  1201. : _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }
  1202. strand(strand&& __other) noexcept
  1203. : _M_state(std::move(__other._M_state)),
  1204. _M_inner_ex(std::move(__other._M_inner_ex)) { }
  1205. template<typename _OtherExecutor>
  1206. strand(const strand<_OtherExecutor>& __other) noexcept
  1207. : _M_state(__other._M_state), _M_inner_ex(__other._M_inner_ex) { }
  1208. template<typename _OtherExecutor>
  1209. strand(strand<_OtherExecutor>&& __other) noexcept
  1210. : _M_state(std::move(__other._M_state)),
  1211. _M_inner_ex(std::move(__other._M_inner_ex)) { }
  1212. strand&
  1213. operator=(const strand& __other) noexcept
  1214. {
  1215. static_assert(is_copy_assignable<_Executor>::value,
  1216. "inner executor type must be CopyAssignable");
  1217. // TODO lock __other
  1218. // TODO copy state
  1219. _M_inner_ex = __other._M_inner_ex;
  1220. return *this;
  1221. }
  1222. strand&
  1223. operator=(strand&& __other) noexcept
  1224. {
  1225. static_assert(is_move_assignable<_Executor>::value,
  1226. "inner executor type must be MoveAssignable");
  1227. // TODO move state
  1228. _M_inner_ex = std::move(__other._M_inner_ex);
  1229. return *this;
  1230. }
  1231. template<typename _OtherExecutor>
  1232. strand&
  1233. operator=(const strand<_OtherExecutor>& __other) noexcept
  1234. {
  1235. static_assert(is_convertible<_OtherExecutor, _Executor>::value,
  1236. "inner executor type must be compatible");
  1237. // TODO lock __other
  1238. // TODO copy state
  1239. _M_inner_ex = __other._M_inner_ex;
  1240. return *this;
  1241. }
  1242. template<typename _OtherExecutor>
  1243. strand&
  1244. operator=(strand<_OtherExecutor>&& __other) noexcept
  1245. {
  1246. static_assert(is_convertible<_OtherExecutor, _Executor>::value,
  1247. "inner executor type must be compatible");
  1248. // TODO move state
  1249. _M_inner_ex = std::move(__other._M_inner_ex);
  1250. return *this;
  1251. }
  1252. ~strand()
  1253. {
  1254. // the task queue outlives this object if non-empty
  1255. // TODO create circular ref in queue?
  1256. }
  1257. // strand operations:
  1258. inner_executor_type
  1259. get_inner_executor() const noexcept
  1260. { return _M_inner_ex; }
  1261. bool
  1262. running_in_this_thread() const noexcept
  1263. { return _M_state->running_in_this_thread(); }
  1264. execution_context&
  1265. context() const noexcept
  1266. { return _M_inner_ex.context(); }
  1267. void on_work_started() const noexcept { _M_inner_ex.on_work_started(); }
  1268. void on_work_finished() const noexcept { _M_inner_ex.on_work_finished(); }
  1269. template<typename _Func, typename _Alloc>
  1270. void
  1271. dispatch(_Func&& __f, const _Alloc& __a) const
  1272. {
  1273. if (running_in_this_thread())
  1274. decay_t<_Func>{std::forward<_Func>(__f)}();
  1275. else
  1276. post(std::forward<_Func>(__f), __a);
  1277. }
  1278. template<typename _Func, typename _Alloc>
  1279. void
  1280. post(_Func&& __f, const _Alloc& __a) const; // TODO
  1281. template<typename _Func, typename _Alloc>
  1282. void
  1283. defer(_Func&& __f, const _Alloc& __a) const
  1284. { post(std::forward<_Func>(__f), __a); }
  1285. private:
  1286. friend bool
  1287. operator==(const strand& __a, const strand& __b)
  1288. { return __a._M_state == __b._M_state; }
  1289. // TODO add synchronised queue
  1290. struct _State
  1291. {
  1292. #if defined(_GLIBCXX_HAS_GTHREADS)
  1293. bool
  1294. running_in_this_thread() const noexcept
  1295. { return std::this_thread::get_id() == _M_running_on; }
  1296. std::thread::id _M_running_on;
  1297. #else
  1298. bool running_in_this_thread() const { return true; }
  1299. #endif
  1300. };
  1301. shared_ptr<_State> _M_state;
  1302. _Executor _M_inner_ex;
  1303. };
  1304. #if defined(_GLIBCXX_HAS_GTHREADS)
  1305. // Completion token for asynchronous operations initiated with use_future.
  1306. template<typename _Func, typename _Alloc>
  1307. struct __use_future_ct
  1308. {
  1309. std::tuple<_Func, _Alloc> _M_t;
  1310. };
  1311. template<typename _Func, typename _Tp>
  1312. struct __use_future_ct<_Func, std::allocator<_Tp>>
  1313. {
  1314. _Func _M_f;
  1315. };
  1316. template<typename _ProtoAllocator = allocator<void>>
  1317. class use_future_t
  1318. {
  1319. public:
  1320. // use_future_t types:
  1321. using allocator_type = _ProtoAllocator;
  1322. // use_future_t members:
  1323. constexpr
  1324. use_future_t()
  1325. noexcept(is_nothrow_default_constructible<_ProtoAllocator>::value)
  1326. : _M_alloc() { }
  1327. explicit
  1328. use_future_t(const _ProtoAllocator& __a) noexcept : _M_alloc(__a) { }
  1329. template<typename _OtherAllocator>
  1330. use_future_t<_OtherAllocator>
  1331. rebind(const _OtherAllocator& __a) const noexcept
  1332. { return use_future_t<_OtherAllocator>(__a); }
  1333. allocator_type get_allocator() const noexcept { return _M_alloc; }
  1334. template<typename _Func>
  1335. auto
  1336. operator()(_Func&& __f) const
  1337. {
  1338. using _Token = __use_future_ct<decay_t<_Func>, _ProtoAllocator>;
  1339. return _Token{ {std::forward<_Func>(__f), _M_alloc} };
  1340. }
  1341. private:
  1342. _ProtoAllocator _M_alloc;
  1343. };
  1344. template<typename _Tp>
  1345. class use_future_t<std::allocator<_Tp>>
  1346. {
  1347. public:
  1348. // use_future_t types:
  1349. using allocator_type = std::allocator<_Tp>;
  1350. // use_future_t members:
  1351. constexpr use_future_t() noexcept = default;
  1352. explicit
  1353. use_future_t(const allocator_type& __a) noexcept { }
  1354. template<class _Up>
  1355. use_future_t<std::allocator<_Up>>
  1356. rebind(const std::allocator<_Up>& __a) const noexcept
  1357. { return use_future_t<std::allocator<_Up>>(__a); }
  1358. allocator_type get_allocator() const noexcept { return {}; }
  1359. template<typename _Func>
  1360. auto
  1361. operator()(_Func&& __f) const
  1362. {
  1363. using _Token = __use_future_ct<decay_t<_Func>, allocator_type>;
  1364. return _Token{std::forward<_Func>(__f)};
  1365. }
  1366. };
  1367. constexpr use_future_t<> use_future = use_future_t<>();
  1368. template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
  1369. class async_result<__use_future_ct<_Func, _Alloc>, _Res(_Args...)>;
  1370. template<typename _Result, typename _Executor>
  1371. struct __use_future_ex;
  1372. // Completion handler for asynchronous operations initiated with use_future.
  1373. template<typename _Func, typename... _Args>
  1374. struct __use_future_ch
  1375. {
  1376. template<typename _Alloc>
  1377. explicit
  1378. __use_future_ch(__use_future_ct<_Func, _Alloc>&& __token)
  1379. : _M_f{ std::move(std::get<0>(__token._M_t)) },
  1380. _M_promise{ std::get<1>(__token._M_t) }
  1381. { }
  1382. template<typename _Tp>
  1383. explicit
  1384. __use_future_ch(__use_future_ct<_Func, std::allocator<_Tp>>&& __token)
  1385. : _M_f{ std::move(__token._M_f) }
  1386. { }
  1387. void
  1388. operator()(_Args&&... __args)
  1389. {
  1390. __try
  1391. {
  1392. _M_promise.set_value(_M_f(std::forward<_Args>(__args)...));
  1393. }
  1394. __catch(__cxxabiv1::__forced_unwind&)
  1395. {
  1396. __throw_exception_again;
  1397. }
  1398. __catch(...)
  1399. {
  1400. _M_promise.set_exception(std::current_exception());
  1401. }
  1402. }
  1403. using __result = result_of_t<_Func(decay_t<_Args>...)>;
  1404. future<__result> get_future() { return _M_promise.get_future(); }
  1405. private:
  1406. template<typename _Result, typename _Executor>
  1407. friend struct __use_future_ex;
  1408. _Func _M_f;
  1409. mutable promise<__result> _M_promise;
  1410. };
  1411. // Specialization of async_result for operations initiated with use_future.
  1412. template<typename _Func, typename _Alloc, typename _Res, typename... _Args>
  1413. class async_result<__use_future_ct<_Func, _Alloc>, _Res(_Args...)>
  1414. {
  1415. public:
  1416. using completion_handler_type = __use_future_ch<_Func, _Args...>;
  1417. using return_type = future<typename completion_handler_type::__result>;
  1418. explicit
  1419. async_result(completion_handler_type& __h)
  1420. : _M_future(__h.get_future())
  1421. { }
  1422. async_result(const async_result&) = delete;
  1423. async_result& operator=(const async_result&) = delete;
  1424. return_type get() { return std::move(_M_future); }
  1425. private:
  1426. return_type _M_future;
  1427. };
  1428. template<typename _Result, typename _Executor>
  1429. struct __use_future_ex
  1430. {
  1431. template<typename _Handler>
  1432. __use_future_ex(const _Handler& __h, _Executor __ex)
  1433. : _M_t(__h._M_promise, __ex)
  1434. { }
  1435. template<typename _Fn, typename _Alloc>
  1436. void
  1437. dispatch(_Fn&& __fn)
  1438. {
  1439. __try
  1440. {
  1441. std::get<1>(_M_t).dispatch(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. template<typename _Fn, typename _Alloc>
  1453. void
  1454. post(_Fn&& __fn)
  1455. {
  1456. __try
  1457. {
  1458. std::get<1>(_M_t).post(std::forward<_Fn>(__fn));
  1459. }
  1460. __catch(__cxxabiv1::__forced_unwind&)
  1461. {
  1462. __throw_exception_again;
  1463. }
  1464. __catch(...)
  1465. {
  1466. std::get<0>(_M_t).set_exception(std::current_exception());
  1467. }
  1468. }
  1469. template<typename _Fn, typename _Alloc>
  1470. void
  1471. defer(_Fn&& __fn)
  1472. {
  1473. __try
  1474. {
  1475. std::get<1>(_M_t).defer(std::forward<_Fn>(__fn));
  1476. }
  1477. __catch(__cxxabiv1::__forced_unwind&)
  1478. {
  1479. __throw_exception_again;
  1480. }
  1481. __catch(...)
  1482. {
  1483. std::get<0>(_M_t).set_exception(std::current_exception());
  1484. }
  1485. }
  1486. private:
  1487. tuple<promise<_Result>&, _Executor> _M_t;
  1488. };
  1489. template<typename _Func, typename... _Args, typename _Executor>
  1490. struct associated_executor<__use_future_ch<_Func, _Args...>, _Executor>
  1491. {
  1492. private:
  1493. using __handler = __use_future_ch<_Func, _Args...>;
  1494. using type = __use_future_ex<typename __handler::__result, _Executor>;
  1495. static type
  1496. get(const __handler& __h, const _Executor& __ex)
  1497. { return { __h, __ex }; }
  1498. };
  1499. #if 0
  1500. // [async.use.future.traits]
  1501. template<typename _Allocator, typename _Ret, typename... _Args>
  1502. class handler_type<use_future_t<_Allocator>, _Ret(_Args...)> // TODO uglify name
  1503. {
  1504. template<typename... _Args>
  1505. struct __is_error_result : false_type { };
  1506. template<typename... _Args>
  1507. struct __is_error_result<error_code, _Args...> : true_type { };
  1508. template<typename... _Args>
  1509. struct __is_error_result<exception_ptr, _Args...> : true_type { };
  1510. static exception_ptr
  1511. _S_exptr(exception_ptr& __ex)
  1512. { return std::move(__ex); }
  1513. static exception_ptr
  1514. _S_exptr(const error_code& __ec)
  1515. { return make_exception_ptr(system_error(__ec)); }
  1516. template<bool _IsError, typename... _UArgs>
  1517. struct _Type;
  1518. // N == 0
  1519. template<bool _IsError>
  1520. struct _Type<_IsError>
  1521. {
  1522. std::promise<void> _M_promise;
  1523. void
  1524. operator()()
  1525. {
  1526. _M_promise.set_value();
  1527. }
  1528. };
  1529. // N == 1, U0 is error_code or exception_ptr
  1530. template<typename _UArg0>
  1531. struct _Type<true, _UArg0>
  1532. {
  1533. std::promise<void> _M_promise;
  1534. template<typename _Arg0>
  1535. void
  1536. operator()(_Arg0&& __a0)
  1537. {
  1538. if (__a0)
  1539. _M_promise.set_exception(_S_exptr(__a0));
  1540. else
  1541. _M_promise.set_value();
  1542. }
  1543. };
  1544. // N == 1, U0 is not error_code or exception_ptr
  1545. template<typename _UArg0>
  1546. struct _Type<false, _UArg0>
  1547. {
  1548. std::promise<_UArg0> _M_promise;
  1549. template<typename _Arg0>
  1550. void
  1551. operator()(_Arg0&& __a0)
  1552. {
  1553. _M_promise.set_value(std::forward<_Arg0>(__a0));
  1554. }
  1555. };
  1556. // N == 2, U0 is error_code or exception_ptr
  1557. template<typename _UArg0, typename _UArg1>
  1558. struct _Type<true, _UArg0, _UArg1>
  1559. {
  1560. std::promise<_UArg1> _M_promise;
  1561. template<typename _Arg0, typename _Arg1>
  1562. void
  1563. operator()(_Arg0&& __a0, _Arg1&& __a1)
  1564. {
  1565. if (__a0)
  1566. _M_promise.set_exception(_S_exptr(__a0));
  1567. else
  1568. _M_promise.set_value(std::forward<_Arg1>(__a1));
  1569. }
  1570. };
  1571. // N >= 2, U0 is not error_code or exception_ptr
  1572. template<typename... _UArgs>
  1573. struct _Type<false, _UArgs...>
  1574. {
  1575. static_assert(sizeof...(_UArgs) > 1, "wrong partial specialization");
  1576. std::promise<tuple<_UArgs...>> _M_promise;
  1577. template<typename... _Args>
  1578. void
  1579. operator()(_Args&&... __args)
  1580. {
  1581. _M_promise.set_value(
  1582. std::forward_as_tuple(std::forward<_Args>(__args)...));
  1583. }
  1584. };
  1585. // N > 2, U0 is error_code or exception_ptr
  1586. template<typename _UArg0, typename... _UArgs>
  1587. struct _Type<true, _UArg0, _UArgs...>
  1588. {
  1589. static_assert(sizeof...(_UArgs) > 1, "wrong partial specialization");
  1590. std::promise<tuple<_UArgs...>> _M_promise;
  1591. template<typename _Arg0, typename... _Args>
  1592. void
  1593. operator()(_Arg0&& __a0, _Args&&... __args)
  1594. {
  1595. if (__a0)
  1596. _M_promise.set_exception(_S_exptr(__a0));
  1597. else
  1598. _M_promise.set_value(
  1599. std::forward_as_tuple(std::forward<_Args>(__args)...));
  1600. }
  1601. };
  1602. public:
  1603. using type =
  1604. _Type<__is_error_result<_Args...>::value, decay_t<_Args>...>;
  1605. };
  1606. template<typename _Alloc, typename _Ret, typename... _Args>
  1607. struct async_result<use_future_t<_Alloc>, _Ret(_Args...)>
  1608. {
  1609. using completion_handler_type
  1610. = typename handler_type<use_future_t<_Alloc>, _Ret(_Args...)>::type;
  1611. using return_type = void; // XXX TODO ???;
  1612. explicit
  1613. async_result(completion_handler_type& __h) : _M_handler(__h) { }
  1614. auto get() { return _M_handler._M_provider.get_future(); }
  1615. async_result(const async_result&) = delete;
  1616. async_result& operator=(const async_result&) = delete;
  1617. return_type get() { return _M_handler._M_promise.get_future(); }
  1618. private:
  1619. completion_handler_type& _M_handler;
  1620. };
  1621. // TODO specialize associated_executor for
  1622. // async_result<use_future_t<A>, Sig>::completion_handler_type
  1623. // to use a __use_future_ex
  1624. // (probably need to move _Type outside of handler_type so we don't have
  1625. // a non-deduced context)
  1626. #endif
  1627. // [async.packaged.task.specializations]
  1628. template<typename _Ret, typename... _Args, typename _Signature>
  1629. class async_result<packaged_task<_Ret(_Args...)>, _Signature>
  1630. {
  1631. public:
  1632. using completion_handler_type = packaged_task<_Ret(_Args...)>;
  1633. using return_type = future<_Ret>;
  1634. explicit
  1635. async_result(completion_handler_type& __h)
  1636. : _M_future(__h.get_future()) { }
  1637. async_result(const async_result&) = delete;
  1638. async_result& operator=(const async_result&) = delete;
  1639. return_type get() { return std::move(_M_future); }
  1640. private:
  1641. return_type _M_future;
  1642. };
  1643. #endif // _GLIBCXX_HAS_GTHREADS
  1644. /// @}
  1645. } // namespace v1
  1646. } // namespace net
  1647. } // namespace experimental
  1648. template<typename _Alloc>
  1649. struct uses_allocator<experimental::net::executor, _Alloc>
  1650. : true_type {};
  1651. _GLIBCXX_END_NAMESPACE_VERSION
  1652. } // namespace std
  1653. #endif // C++14
  1654. #endif // _GLIBCXX_EXPERIMENTAL_EXECUTOR