receiver.h 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  1. #pragma once
  2. /*
  3. * Copyright 2018-present Facebook, Inc.
  4. *
  5. * Licensed under the Apache License, Version 2.0 (the "License");
  6. * you may not use this file except in compliance with the License.
  7. * You may obtain a copy of the License at
  8. *
  9. * http://www.apache.org/licenses/LICENSE-2.0
  10. *
  11. * Unless required by applicable law or agreed to in writing, software
  12. * distributed under the License is distributed on an "AS IS" BASIS,
  13. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. * See the License for the specific language governing permissions and
  15. * limitations under the License.
  16. */
  17. #include <folly/experimental/pushmi/boosters.h>
  18. #include <future>
  19. namespace pushmi {
  20. template <class E, class... VN>
  21. class any_receiver {
  22. bool done_ = false;
  23. union data {
  24. void* pobj_ = nullptr;
  25. char buffer_[sizeof(std::promise<int>)]; // can hold a std::promise in-situ
  26. } data_{};
  27. template <class Wrapped>
  28. static constexpr bool insitu() noexcept {
  29. return sizeof(Wrapped) <= sizeof(data::buffer_) &&
  30. std::is_nothrow_move_constructible<Wrapped>::value;
  31. }
  32. struct vtable {
  33. static void s_op(data&, data*) {}
  34. static void s_done(data&) {}
  35. static void s_error(data&, E) noexcept {
  36. std::terminate();
  37. }
  38. static void s_value(data&, VN...) {}
  39. void (*op_)(data&, data*) = vtable::s_op;
  40. void (*done_)(data&) = vtable::s_done;
  41. void (*error_)(data&, E) noexcept = vtable::s_error;
  42. void (*value_)(data&, VN...) = vtable::s_value;
  43. };
  44. static constexpr vtable const noop_{};
  45. vtable const* vptr_ = &noop_;
  46. template <class T, class U = std::decay_t<T>>
  47. using wrapped_t = std::enable_if_t<!std::is_same<U, any_receiver>::value, U>;
  48. template <class Wrapped>
  49. static void check() {
  50. static_assert(
  51. ReceiveValue<Wrapped, VN...>,
  52. "Wrapped receiver must support values of type VN...");
  53. static_assert(
  54. ReceiveError<Wrapped, std::exception_ptr>,
  55. "Wrapped receiver must support std::exception_ptr and be noexcept");
  56. static_assert(
  57. NothrowInvocable<decltype(::pushmi::set_error), Wrapped, E>,
  58. "Wrapped receiver must support E and be noexcept");
  59. }
  60. template <class Wrapped>
  61. any_receiver(Wrapped obj, std::false_type) : any_receiver() {
  62. struct s {
  63. static void op(data& src, data* dst) {
  64. if (dst)
  65. dst->pobj_ = std::exchange(src.pobj_, nullptr);
  66. delete static_cast<Wrapped const*>(src.pobj_);
  67. }
  68. static void done(data& src) {
  69. ::pushmi::set_done(*static_cast<Wrapped*>(src.pobj_));
  70. }
  71. static void error(data& src, E e) noexcept {
  72. ::pushmi::set_error(*static_cast<Wrapped*>(src.pobj_), std::move(e));
  73. }
  74. static void value(data& src, VN... vn) {
  75. ::pushmi::set_value(
  76. *static_cast<Wrapped*>(src.pobj_), std::move(vn)...);
  77. }
  78. };
  79. static const vtable vtbl{s::op, s::done, s::error, s::value};
  80. data_.pobj_ = new Wrapped(std::move(obj));
  81. vptr_ = &vtbl;
  82. }
  83. template <class Wrapped>
  84. any_receiver(Wrapped obj, std::true_type) noexcept : any_receiver() {
  85. struct s {
  86. static void op(data& src, data* dst) {
  87. if (dst)
  88. new (dst->buffer_)
  89. Wrapped(std::move(*static_cast<Wrapped*>((void*)src.buffer_)));
  90. static_cast<Wrapped const*>((void*)src.buffer_)->~Wrapped();
  91. }
  92. static void done(data& src) {
  93. ::pushmi::set_done(*static_cast<Wrapped*>((void*)src.buffer_));
  94. }
  95. static void error(data& src, E e) noexcept {
  96. ::pushmi::set_error(
  97. *static_cast<Wrapped*>((void*)src.buffer_), std::move(e));
  98. }
  99. static void value(data& src, VN... vn) {
  100. ::pushmi::set_value(
  101. *static_cast<Wrapped*>((void*)src.buffer_), std::move(vn)...);
  102. }
  103. };
  104. static const vtable vtbl{s::op, s::done, s::error, s::value};
  105. new ((void*)data_.buffer_) Wrapped(std::move(obj));
  106. vptr_ = &vtbl;
  107. }
  108. public:
  109. using properties = property_set<is_receiver<>>;
  110. any_receiver() = default;
  111. any_receiver(any_receiver&& that) noexcept : any_receiver() {
  112. that.vptr_->op_(that.data_, &data_);
  113. std::swap(that.vptr_, vptr_);
  114. }
  115. PUSHMI_TEMPLATE(class Wrapped)
  116. (requires ReceiveValue<wrapped_t<Wrapped>, VN...>&& ReceiveError<
  117. Wrapped,
  118. E>)
  119. explicit any_receiver(Wrapped obj) noexcept(insitu<Wrapped>())
  120. : any_receiver{std::move(obj), bool_<insitu<Wrapped>()>{}} {
  121. check<Wrapped>();
  122. }
  123. ~any_receiver() {
  124. vptr_->op_(data_, nullptr);
  125. }
  126. any_receiver& operator=(any_receiver&& that) noexcept {
  127. this->~any_receiver();
  128. new ((void*)this) any_receiver(std::move(that));
  129. return *this;
  130. }
  131. void value(VN&&... vn) {
  132. if (!done_) {
  133. // done_ = true;
  134. vptr_->value_(data_, (VN &&) vn...);
  135. }
  136. }
  137. void error(E e) noexcept {
  138. if (!done_) {
  139. done_ = true;
  140. vptr_->error_(data_, std::move(e));
  141. }
  142. }
  143. void done() {
  144. if (!done_) {
  145. done_ = true;
  146. vptr_->done_(data_);
  147. }
  148. }
  149. };
  150. // Class static definitions:
  151. template <class E, class... VN>
  152. constexpr
  153. typename any_receiver<E, VN...>::vtable const any_receiver<E, VN...>::noop_;
  154. template <class VF, class EF, class DF>
  155. #if __cpp_concepts
  156. requires Invocable<DF&>
  157. #endif
  158. class receiver<VF, EF, DF> {
  159. bool done_ = false;
  160. VF vf_;
  161. EF ef_;
  162. DF df_;
  163. static_assert(
  164. !detail::is_v<VF, on_error_fn>,
  165. "the first parameter is the value implementation, but on_error{} was passed");
  166. static_assert(
  167. !detail::is_v<EF, on_value_fn>,
  168. "the second parameter is the error implementation, but on_value{} was passed");
  169. static_assert(
  170. NothrowInvocable<EF&, std::exception_ptr>,
  171. "error function must be noexcept and support std::exception_ptr");
  172. public:
  173. using properties = property_set<is_receiver<>>;
  174. receiver() = default;
  175. constexpr explicit receiver(VF vf) : receiver(std::move(vf), EF{}, DF{}) {}
  176. constexpr explicit receiver(EF ef) : receiver(VF{}, std::move(ef), DF{}) {}
  177. constexpr explicit receiver(DF df) : receiver(VF{}, EF{}, std::move(df)) {}
  178. constexpr receiver(EF ef, DF df)
  179. : done_(false), vf_(), ef_(std::move(ef)), df_(std::move(df)) {}
  180. constexpr receiver(VF vf, EF ef, DF df = DF{})
  181. : done_(false),
  182. vf_(std::move(vf)),
  183. ef_(std::move(ef)),
  184. df_(std::move(df)) {}
  185. PUSHMI_TEMPLATE(class... VN)
  186. (requires Invocable<VF&, VN...>)
  187. void value(VN&&... vn) {
  188. if (done_) {
  189. return;
  190. }
  191. // done_ = true;
  192. vf_((VN &&) vn...);
  193. }
  194. PUSHMI_TEMPLATE(class E)
  195. (requires Invocable<EF&, E>)
  196. void error(E e) noexcept {
  197. static_assert(NothrowInvocable<EF&, E>, "error function must be noexcept");
  198. if (!done_) {
  199. done_ = true;
  200. ef_(std::move(e));
  201. }
  202. }
  203. void done() {
  204. if (!done_) {
  205. done_ = true;
  206. df_();
  207. }
  208. }
  209. };
  210. template <
  211. PUSHMI_TYPE_CONSTRAINT(Receiver) Data,
  212. class DVF,
  213. class DEF,
  214. class DDF>
  215. #if __cpp_concepts
  216. requires Invocable<DDF&, Data&>
  217. #endif
  218. class receiver<Data, DVF, DEF, DDF> {
  219. bool done_ = false;
  220. Data data_;
  221. DVF vf_;
  222. DEF ef_;
  223. DDF df_;
  224. static_assert(
  225. !detail::is_v<DVF, on_error_fn>,
  226. "the first parameter is the value implementation, but on_error{} was passed");
  227. static_assert(
  228. !detail::is_v<DEF, on_value_fn>,
  229. "the second parameter is the error implementation, but on_value{} was passed");
  230. static_assert(
  231. Invocable<DEF, Data&, std::exception_ptr>,
  232. "error function must support std::exception_ptr");
  233. static_assert(
  234. NothrowInvocable<DEF, Data&, std::exception_ptr>,
  235. "error function must be noexcept");
  236. public:
  237. using properties =
  238. property_set_insert_t<properties_t<Data>, property_set<is_receiver<>>>;
  239. constexpr explicit receiver(Data d)
  240. : receiver(std::move(d), DVF{}, DEF{}, DDF{}) {}
  241. constexpr receiver(Data d, DDF df)
  242. : done_(false), data_(std::move(d)), vf_(), ef_(), df_(df) {}
  243. constexpr receiver(Data d, DEF ef, DDF df = DDF{})
  244. : done_(false), data_(std::move(d)), vf_(), ef_(ef), df_(df) {}
  245. constexpr receiver(Data d, DVF vf, DEF ef = DEF{}, DDF df = DDF{})
  246. : done_(false), data_(std::move(d)), vf_(vf), ef_(ef), df_(df) {}
  247. Data& data() {
  248. return data_;
  249. }
  250. PUSHMI_TEMPLATE(class... VN)
  251. (requires Invocable<DVF&, Data&, VN...>)
  252. void value(VN&&... vn) {
  253. if (!done_) {
  254. // done_ = true;
  255. vf_(data_, (VN &&) vn...);
  256. }
  257. }
  258. PUSHMI_TEMPLATE(class E)
  259. (requires Invocable<DEF&, Data&, E>)
  260. void error(E e) noexcept {
  261. static_assert(
  262. NothrowInvocable<DEF&, Data&, E>, "error function must be noexcept");
  263. if (!done_) {
  264. done_ = true;
  265. ef_(data_, std::move(e));
  266. }
  267. }
  268. void done() {
  269. if (!done_) {
  270. done_ = true;
  271. df_(data_);
  272. }
  273. }
  274. };
  275. template <>
  276. class receiver<> : public receiver<ignoreVF, abortEF, ignoreDF> {
  277. public:
  278. receiver() = default;
  279. };
  280. PUSHMI_CONCEPT_DEF(
  281. template (class T)
  282. concept ReceiverDataArg,
  283. Receiver<T> &&
  284. not Invocable<T&>
  285. );
  286. ////////////////////////////////////////////////////////////////////////////////
  287. // make_receiver
  288. PUSHMI_INLINE_VAR constexpr struct make_receiver_fn {
  289. inline auto operator()() const {
  290. return receiver<>{};
  291. }
  292. PUSHMI_TEMPLATE(class VF)
  293. (requires PUSHMI_EXP(
  294. lazy::True<>
  295. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::ReceiverDataArg<VF>)))
  296. auto operator()(VF vf) const {
  297. return receiver<VF, abortEF, ignoreDF>{std::move(vf)};
  298. }
  299. template <class... EFN>
  300. auto operator()(on_error_fn<EFN...> ef) const {
  301. return receiver<ignoreVF, on_error_fn<EFN...>, ignoreDF>{std::move(ef)};
  302. }
  303. template <class... DFN>
  304. auto operator()(on_done_fn<DFN...> df) const {
  305. return receiver<ignoreVF, abortEF, on_done_fn<DFN...>>{std::move(df)};
  306. }
  307. PUSHMI_TEMPLATE(class VF, class EF)
  308. (requires PUSHMI_EXP(
  309. lazy::True<>
  310. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  311. not lazy::ReceiverDataArg<VF> PUSHMI_AND
  312. not lazy::Invocable<EF&>)))
  313. auto operator()(VF vf, EF ef) const {
  314. return receiver<VF, EF, ignoreDF>{std::move(vf), std::move(ef)};
  315. }
  316. PUSHMI_TEMPLATE(class EF, class DF)
  317. (requires PUSHMI_EXP(
  318. lazy::True<> PUSHMI_AND
  319. lazy::Invocable<DF&>
  320. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::ReceiverDataArg<EF>)))
  321. auto operator()(EF ef, DF df) const {
  322. return receiver<ignoreVF, EF, DF>{std::move(ef), std::move(df)};
  323. }
  324. PUSHMI_TEMPLATE(class VF, class EF, class DF)
  325. (requires PUSHMI_EXP(
  326. lazy::True<> PUSHMI_AND
  327. lazy::Invocable<DF&>
  328. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::ReceiverDataArg<VF>)))
  329. auto operator()(VF vf, EF ef, DF df) const {
  330. return receiver<VF, EF, DF>{std::move(vf), std::move(ef), std::move(df)};
  331. }
  332. PUSHMI_TEMPLATE(class Data)
  333. (requires PUSHMI_EXP(
  334. lazy::True<> PUSHMI_AND
  335. lazy::ReceiverDataArg<Data>))
  336. auto operator()(Data d) const {
  337. return receiver<Data, passDVF, passDEF, passDDF>{std::move(d)};
  338. }
  339. PUSHMI_TEMPLATE(class Data, class DVF)
  340. (requires PUSHMI_EXP(
  341. lazy::True<> PUSHMI_AND
  342. lazy::ReceiverDataArg<Data>))
  343. auto operator()(Data d, DVF vf) const {
  344. return receiver<Data, DVF, passDEF, passDDF>{std::move(d), std::move(vf)};
  345. }
  346. PUSHMI_TEMPLATE(class Data, class... DEFN)
  347. (requires PUSHMI_EXP(
  348. lazy::True<> PUSHMI_AND
  349. lazy::ReceiverDataArg<Data>))
  350. auto operator()(Data d, on_error_fn<DEFN...> ef) const {
  351. return receiver<Data, passDVF, on_error_fn<DEFN...>, passDDF>{std::move(d), std::move(ef)};
  352. }
  353. PUSHMI_TEMPLATE(class Data, class... DDFN)
  354. (requires PUSHMI_EXP(
  355. lazy::True<> PUSHMI_AND
  356. lazy::ReceiverDataArg<Data>))
  357. auto operator()(Data d, on_done_fn<DDFN...> df) const {
  358. return receiver<Data, passDVF, passDEF, on_done_fn<DDFN...>>{std::move(d), std::move(df)};
  359. }
  360. PUSHMI_TEMPLATE(class Data, class DVF, class... DEFN)
  361. (requires PUSHMI_EXP(
  362. lazy::True<> PUSHMI_AND
  363. lazy::ReceiverDataArg<Data>))
  364. auto operator()(Data d, DVF vf, on_error_fn<DEFN...> ef) const {
  365. return receiver<Data, DVF, on_error_fn<DEFN...>, passDDF>{std::move(d), std::move(vf), std::move(ef)};
  366. }
  367. PUSHMI_TEMPLATE(class Data, class DEF, class... DDFN)
  368. (requires PUSHMI_EXP(
  369. lazy::True<> PUSHMI_AND
  370. lazy::ReceiverDataArg<Data>))
  371. auto operator()(Data d, DEF ef, on_done_fn<DDFN...> df) const {
  372. return receiver<Data, passDVF, DEF, on_done_fn<DDFN...>>{std::move(d), std::move(ef), std::move(df)};
  373. }
  374. PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF)
  375. (requires PUSHMI_EXP(
  376. lazy::True<> PUSHMI_AND
  377. lazy::ReceiverDataArg<Data> PUSHMI_AND
  378. lazy::Invocable<DDF&, Data&>))
  379. auto operator()(Data d, DVF vf, DEF ef, DDF df) const {
  380. return receiver<Data, DVF, DEF, DDF>{std::move(d), std::move(vf), std::move(ef), std::move(df)};
  381. }
  382. } const make_receiver {};
  383. ////////////////////////////////////////////////////////////////////////////////
  384. // deduction guides
  385. #if __cpp_deduction_guides >= 201703
  386. receiver() -> receiver<>;
  387. PUSHMI_TEMPLATE(class VF)
  388. (requires PUSHMI_EXP(
  389. True<>
  390. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Receiver<VF>)))
  391. receiver(VF) -> receiver<VF, abortEF, ignoreDF>;
  392. template <class... EFN>
  393. receiver(on_error_fn<EFN...>) -> receiver<ignoreVF, on_error_fn<EFN...>, ignoreDF>;
  394. template <class... DFN>
  395. receiver(on_done_fn<DFN...>) -> receiver<ignoreVF, abortEF, on_done_fn<DFN...>>;
  396. PUSHMI_TEMPLATE(class VF, class EF)
  397. (requires PUSHMI_EXP(
  398. lazy::True<>
  399. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  400. not lazy::ReceiverDataArg<VF> PUSHMI_AND
  401. not lazy::Invocable<EF&>)))
  402. receiver(VF, EF) -> receiver<VF, EF, ignoreDF>;
  403. PUSHMI_TEMPLATE(class EF, class DF)
  404. (requires PUSHMI_EXP(
  405. lazy::True<> PUSHMI_AND
  406. lazy::Invocable<DF&>
  407. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::ReceiverDataArg<EF>)))
  408. receiver(EF, DF) -> receiver<ignoreVF, EF, DF>;
  409. PUSHMI_TEMPLATE(class VF, class EF, class DF)
  410. (requires PUSHMI_EXP(
  411. lazy::True<> PUSHMI_AND
  412. lazy::Invocable<DF&>
  413. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::ReceiverDataArg<VF>)))
  414. receiver(VF, EF, DF) -> receiver<VF, EF, DF>;
  415. PUSHMI_TEMPLATE(class Data)
  416. (requires PUSHMI_EXP(
  417. lazy::True<> PUSHMI_AND
  418. lazy::ReceiverDataArg<Data>))
  419. receiver(Data d) -> receiver<Data, passDVF, passDEF, passDDF>;
  420. PUSHMI_TEMPLATE(class Data, class DVF)
  421. (requires PUSHMI_EXP(
  422. lazy::True<> PUSHMI_AND
  423. lazy::ReceiverDataArg<Data>))
  424. receiver(Data d, DVF vf) -> receiver<Data, DVF, passDEF, passDDF>;
  425. PUSHMI_TEMPLATE(class Data, class... DEFN)
  426. (requires PUSHMI_EXP(
  427. lazy::True<> PUSHMI_AND
  428. lazy::ReceiverDataArg<Data>))
  429. receiver(Data d, on_error_fn<DEFN...>) ->
  430. receiver<Data, passDVF, on_error_fn<DEFN...>, passDDF>;
  431. PUSHMI_TEMPLATE(class Data, class... DDFN)
  432. (requires PUSHMI_EXP(
  433. lazy::True<> PUSHMI_AND
  434. lazy::ReceiverDataArg<Data>))
  435. receiver(Data d, on_done_fn<DDFN...>) ->
  436. receiver<Data, passDVF, passDEF, on_done_fn<DDFN...>>;
  437. PUSHMI_TEMPLATE(class Data, class DVF, class... DEFN)
  438. (requires PUSHMI_EXP(
  439. lazy::True<> PUSHMI_AND
  440. lazy::ReceiverDataArg<Data>))
  441. receiver(Data d, DVF vf, on_error_fn<DEFN...> ef) -> receiver<Data, DVF, on_error_fn<DEFN...>, passDDF>;
  442. PUSHMI_TEMPLATE(class Data, class DEF, class... DDFN)
  443. (requires PUSHMI_EXP(
  444. lazy::True<> PUSHMI_AND
  445. lazy::ReceiverDataArg<Data>
  446. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND not lazy::Invocable<DEF&, Data&>)))
  447. receiver(Data d, DEF, on_done_fn<DDFN...>) -> receiver<Data, passDVF, DEF, on_done_fn<DDFN...>>;
  448. PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF)
  449. (requires PUSHMI_EXP(
  450. lazy::True<> PUSHMI_AND
  451. lazy::ReceiverDataArg<Data>PUSHMI_AND
  452. lazy::Invocable<DDF&, Data&>))
  453. receiver(Data d, DVF vf, DEF ef, DDF df) -> receiver<Data, DVF, DEF, DDF>;
  454. #endif
  455. template<>
  456. struct construct_deduced<receiver> : make_receiver_fn {};
  457. PUSHMI_TEMPLATE (class T, class In)
  458. (requires SenderTo<In, std::promise<T>, is_single<>>)
  459. std::future<T> future_from(In in) {
  460. std::promise<T> p;
  461. auto result = p.get_future();
  462. submit(in, std::move(p));
  463. return result;
  464. }
  465. PUSHMI_TEMPLATE (class In)
  466. (requires SenderTo<In, std::promise<void>, is_single<>>)
  467. std::future<void> future_from(In in) {
  468. std::promise<void> p;
  469. auto result = p.get_future();
  470. submit(in, std::move(p));
  471. return result;
  472. }
  473. } // namespace pushmi