flow_receiver.h 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  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/receiver.h>
  18. namespace pushmi {
  19. template <class PE, class PV, class E, class... VN>
  20. class any_flow_receiver {
  21. bool done_ = false;
  22. bool started_ = false;
  23. union data {
  24. void* pobj_ = nullptr;
  25. char buffer_[sizeof(std::tuple<VN...>)]; // can hold V in-situ
  26. } data_{};
  27. template <class Wrapped>
  28. static constexpr bool insitu() {
  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 { std::terminate(); }
  36. static void s_value(data&, VN...) {}
  37. static void s_starting(data&, any_receiver<PE, PV>) {}
  38. void (*op_)(data&, data*) = vtable::s_op;
  39. void (*done_)(data&) = vtable::s_done;
  40. void (*error_)(data&, E) noexcept = vtable::s_error;
  41. void (*value_)(data&, VN...) = vtable::s_value;
  42. void (*starting_)(data&, any_receiver<PE, PV>) = vtable::s_starting;
  43. };
  44. static constexpr vtable const noop_ {};
  45. vtable const* vptr_ = &noop_;
  46. template <class Wrapped>
  47. any_flow_receiver(Wrapped obj, std::false_type) : any_flow_receiver() {
  48. struct s {
  49. static void op(data& src, data* dst) {
  50. if (dst)
  51. dst->pobj_ = std::exchange(src.pobj_, nullptr);
  52. delete static_cast<Wrapped const*>(src.pobj_);
  53. }
  54. static void done(data& src) {
  55. ::pushmi::set_done(*static_cast<Wrapped*>(src.pobj_));
  56. }
  57. static void error(data& src, E e) noexcept {
  58. ::pushmi::set_error(*static_cast<Wrapped*>(src.pobj_), std::move(e));
  59. }
  60. static void value(data& src, VN... vn) {
  61. ::pushmi::set_value(*static_cast<Wrapped*>(src.pobj_), std::move(vn)...);
  62. }
  63. static void starting(data& src, any_receiver<PE, PV> up) {
  64. ::pushmi::set_starting(*static_cast<Wrapped*>(src.pobj_), std::move(up));
  65. }
  66. };
  67. static const vtable vtbl{s::op, s::done, s::error, s::value, s::starting};
  68. data_.pobj_ = new Wrapped(std::move(obj));
  69. vptr_ = &vtbl;
  70. }
  71. template <class Wrapped>
  72. any_flow_receiver(Wrapped obj, std::true_type) noexcept : any_flow_receiver() {
  73. struct s {
  74. static void op(data& src, data* dst) {
  75. if (dst)
  76. new (dst->buffer_) Wrapped(
  77. std::move(*static_cast<Wrapped*>((void*)src.buffer_)));
  78. static_cast<Wrapped const*>((void*)src.buffer_)->~Wrapped();
  79. }
  80. static void done(data& src) {
  81. ::pushmi::set_done(*static_cast<Wrapped*>((void*)src.buffer_));
  82. }
  83. static void error(data& src, E e) noexcept {::pushmi::set_error(
  84. *static_cast<Wrapped*>((void*)src.buffer_),
  85. std::move(e));
  86. }
  87. static void value(data& src, VN... vn) {
  88. ::pushmi::set_value(
  89. *static_cast<Wrapped*>((void*)src.buffer_), std::move(vn)...);
  90. }
  91. static void starting(data& src, any_receiver<PE, PV> up) {
  92. ::pushmi::set_starting(*static_cast<Wrapped*>((void*)src.buffer_), std::move(up));
  93. }
  94. };
  95. static const vtable vtbl{s::op, s::done, s::error, s::value, s::starting};
  96. new (data_.buffer_) Wrapped(std::move(obj));
  97. vptr_ = &vtbl;
  98. }
  99. template <class T, class U = std::decay_t<T>>
  100. using wrapped_t =
  101. std::enable_if_t<!std::is_same<U, any_flow_receiver>::value, U>;
  102. public:
  103. using properties = property_set<is_receiver<>, is_flow<>>;
  104. any_flow_receiver() = default;
  105. any_flow_receiver(any_flow_receiver&& that) noexcept : any_flow_receiver() {
  106. that.vptr_->op_(that.data_, &data_);
  107. std::swap(that.vptr_, vptr_);
  108. }
  109. PUSHMI_TEMPLATE(class Wrapped)
  110. (requires FlowUpTo<wrapped_t<Wrapped>, any_receiver<PE, PV>> &&
  111. ReceiveValue<wrapped_t<Wrapped>, VN...> &&
  112. ReceiveError<wrapped_t<Wrapped>, E>)
  113. explicit any_flow_receiver(Wrapped obj) noexcept(insitu<Wrapped>())
  114. : any_flow_receiver{std::move(obj), bool_<insitu<Wrapped>()>{}} {}
  115. ~any_flow_receiver() {
  116. vptr_->op_(data_, nullptr);
  117. }
  118. any_flow_receiver& operator=(any_flow_receiver&& that) noexcept {
  119. this->~any_flow_receiver();
  120. new ((void*)this) any_flow_receiver(std::move(that));
  121. return *this;
  122. }
  123. void value(VN... vn) {
  124. if (!started_) {std::abort();}
  125. if (done_){ return; }
  126. vptr_->value_(data_, std::move(vn)...);
  127. }
  128. void error(E e) noexcept {
  129. if (!started_) {std::abort();}
  130. if (done_){ return; }
  131. done_ = true;
  132. vptr_->error_(data_, std::move(e));
  133. }
  134. void done() {
  135. if (!started_) {std::abort();}
  136. if (done_){ return; }
  137. done_ = true;
  138. vptr_->done_(data_);
  139. }
  140. void starting(any_receiver<PE, PV> up) {
  141. if (started_) {std::abort();}
  142. started_ = true;
  143. vptr_->starting_(data_, std::move(up));
  144. }
  145. };
  146. // Class static definitions:
  147. template <class PE, class PV, class E, class... VN>
  148. constexpr typename any_flow_receiver<PE, PV, E, VN...>::vtable const
  149. any_flow_receiver<PE, PV, E, VN...>::noop_;
  150. template <class VF, class EF, class DF, class StrtF>
  151. #if __cpp_concepts
  152. requires Invocable<DF&>
  153. #endif
  154. class flow_receiver<VF, EF, DF, StrtF> {
  155. bool done_ = false;
  156. bool started_ = false;
  157. VF nf_;
  158. EF ef_;
  159. DF df_;
  160. StrtF strtf_;
  161. public:
  162. using properties = property_set<is_receiver<>, is_flow<>>;
  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. flow_receiver() = default;
  170. constexpr explicit flow_receiver(VF nf)
  171. : flow_receiver(std::move(nf), EF{}, DF{}) {}
  172. constexpr explicit flow_receiver(EF ef)
  173. : flow_receiver(VF{}, std::move(ef), DF{}) {}
  174. constexpr explicit flow_receiver(DF df)
  175. : flow_receiver(VF{}, EF{}, std::move(df)) {}
  176. constexpr flow_receiver(EF ef, DF df)
  177. : nf_(), ef_(std::move(ef)), df_(std::move(df)) {}
  178. constexpr flow_receiver(
  179. VF nf,
  180. EF ef,
  181. DF df = DF{},
  182. StrtF strtf = StrtF{})
  183. : nf_(std::move(nf)),
  184. ef_(std::move(ef)),
  185. df_(std::move(df)),
  186. strtf_(std::move(strtf)) {}
  187. PUSHMI_TEMPLATE (class V)
  188. (requires Invocable<VF&, V>)
  189. void value(V&& v) {
  190. if (!started_) {std::abort();}
  191. if (done_){ return; }
  192. nf_((V&&) v);
  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 (!started_) {std::abort();}
  199. if (done_){ return; }
  200. done_ = true;
  201. ef_(std::move(e));
  202. }
  203. void done() {
  204. if (!started_) {std::abort();}
  205. if (done_){ return; }
  206. done_ = true;
  207. df_();
  208. }
  209. PUSHMI_TEMPLATE(class Up)
  210. (requires Invocable<StrtF&, Up&&>)
  211. void starting(Up&& up) {
  212. if (started_) {std::abort();}
  213. started_ = true;
  214. strtf_( (Up &&) up);
  215. }
  216. };
  217. template<
  218. PUSHMI_TYPE_CONSTRAINT(Receiver) Data,
  219. class DVF,
  220. class DEF,
  221. class DDF,
  222. class DStrtF>
  223. #if __cpp_concepts
  224. requires Invocable<DDF&, Data&>
  225. #endif
  226. class flow_receiver<Data, DVF, DEF, DDF, DStrtF> {
  227. bool done_ = false;
  228. bool started_ = false;
  229. Data data_;
  230. DVF nf_;
  231. DEF ef_;
  232. DDF df_;
  233. DStrtF strtf_;
  234. public:
  235. using properties = property_set_insert_t<properties_t<Data>, property_set<is_receiver<>, is_flow<>>>;
  236. static_assert(
  237. !detail::is_v<DVF, on_error_fn>,
  238. "the first parameter is the value implementation, but on_error{} was passed");
  239. static_assert(
  240. !detail::is_v<DEF, on_value_fn>,
  241. "the second parameter is the error implementation, but on_value{} was passed");
  242. constexpr explicit flow_receiver(Data d)
  243. : flow_receiver(std::move(d), DVF{}, DEF{}, DDF{}) {}
  244. constexpr flow_receiver(Data d, DDF df)
  245. : data_(std::move(d)), nf_(), ef_(), df_(df) {}
  246. constexpr flow_receiver(Data d, DEF ef, DDF df = DDF{})
  247. : data_(std::move(d)), nf_(), ef_(ef), df_(df) {}
  248. constexpr flow_receiver(
  249. Data d,
  250. DVF nf,
  251. DEF ef = DEF{},
  252. DDF df = DDF{},
  253. DStrtF strtf = DStrtF{})
  254. : data_(std::move(d)),
  255. nf_(nf),
  256. ef_(ef),
  257. df_(df),
  258. strtf_(std::move(strtf)) {}
  259. Data& data() { return data_; }
  260. PUSHMI_TEMPLATE (class V)
  261. (requires Invocable<DVF&, Data&, V>)
  262. void value(V&& v) {
  263. if (!started_) {std::abort();}
  264. if (done_){ return; }
  265. nf_(data_, (V&&) v);
  266. }
  267. PUSHMI_TEMPLATE (class E)
  268. (requires Invocable<DEF&, Data&, E>)
  269. void error(E&& e) noexcept {
  270. static_assert(
  271. NothrowInvocable<DEF&, Data&, E>, "error function must be noexcept");
  272. if (!started_) {std::abort();}
  273. if (done_){ return; }
  274. done_ = true;
  275. ef_(data_, (E&&) e);
  276. }
  277. void done() {
  278. if (!started_) {std::abort();}
  279. if (done_){ return; }
  280. done_ = true;
  281. df_(data_);
  282. }
  283. PUSHMI_TEMPLATE (class Up)
  284. (requires Invocable<DStrtF&, Data&, Up&&>)
  285. void starting(Up&& up) {
  286. if (started_) {std::abort();}
  287. started_ = true;
  288. strtf_(data_, (Up &&) up);
  289. }
  290. };
  291. template <>
  292. class flow_receiver<>
  293. : public flow_receiver<ignoreVF, abortEF, ignoreDF, ignoreStrtF> {
  294. };
  295. PUSHMI_CONCEPT_DEF(
  296. template (class T)
  297. concept FlowReceiverDataArg,
  298. Receiver<T, is_flow<>> &&
  299. not Invocable<T&>
  300. );
  301. // TODO winnow down the number of make_flow_receiver overloads and deduction
  302. // guides here, as was done for make_many.
  303. ////////////////////////////////////////////////////////////////////////////////
  304. // make_flow_receiver
  305. PUSHMI_INLINE_VAR constexpr struct make_flow_receiver_fn {
  306. inline auto operator()() const {
  307. return flow_receiver<>{};
  308. }
  309. PUSHMI_TEMPLATE (class VF)
  310. (requires PUSHMI_EXP(
  311. lazy::True<>
  312. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  313. not lazy::FlowReceiverDataArg<VF>)))
  314. auto operator()(VF nf) const {
  315. return flow_receiver<VF, abortEF, ignoreDF, ignoreStrtF>{
  316. std::move(nf)};
  317. }
  318. template <class... EFN>
  319. auto operator()(on_error_fn<EFN...> ef) const {
  320. return flow_receiver<ignoreVF, on_error_fn<EFN...>, ignoreDF, ignoreStrtF>{
  321. std::move(ef)};
  322. }
  323. template <class... DFN>
  324. auto operator()(on_done_fn<DFN...> df) const {
  325. return flow_receiver<ignoreVF, abortEF, on_done_fn<DFN...>, ignoreStrtF>{
  326. std::move(df)};
  327. }
  328. PUSHMI_TEMPLATE (class VF, class EF)
  329. (requires PUSHMI_EXP(
  330. lazy::True<>
  331. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  332. not lazy::FlowReceiverDataArg<VF> PUSHMI_AND
  333. not lazy::Invocable<EF&>)))
  334. auto operator()(VF nf, EF ef) const {
  335. return flow_receiver<VF, EF, ignoreDF, ignoreStrtF>{std::move(nf),
  336. std::move(ef)};
  337. }
  338. PUSHMI_TEMPLATE(class EF, class DF)
  339. (requires PUSHMI_EXP(
  340. lazy::True<> PUSHMI_AND
  341. lazy::Invocable<DF&>
  342. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  343. not lazy::FlowReceiverDataArg<EF>)))
  344. auto operator()(EF ef, DF df) const {
  345. return flow_receiver<ignoreVF, EF, DF, ignoreStrtF>{std::move(ef), std::move(df)};
  346. }
  347. PUSHMI_TEMPLATE (class VF, class EF, class DF)
  348. (requires PUSHMI_EXP(
  349. lazy::Invocable<DF&>
  350. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  351. not lazy::FlowReceiverDataArg<VF>)))
  352. auto operator()(VF nf, EF ef, DF df) const {
  353. return flow_receiver<VF, EF, DF, ignoreStrtF>{std::move(nf),
  354. std::move(ef), std::move(df)};
  355. }
  356. PUSHMI_TEMPLATE (class VF, class EF, class DF, class StrtF)
  357. (requires PUSHMI_EXP(
  358. lazy::Invocable<DF&>
  359. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  360. not lazy::FlowReceiverDataArg<VF>)))
  361. auto operator()(VF nf, EF ef, DF df, StrtF strtf) const {
  362. return flow_receiver<VF, EF, DF, StrtF>{std::move(nf), std::move(ef),
  363. std::move(df), std::move(strtf)};
  364. }
  365. PUSHMI_TEMPLATE(class Data)
  366. (requires PUSHMI_EXP(
  367. lazy::True<> PUSHMI_AND
  368. lazy::FlowReceiverDataArg<Data>))
  369. auto operator()(Data d) const {
  370. return flow_receiver<Data, passDVF, passDEF, passDDF, passDStrtF>{
  371. std::move(d)};
  372. }
  373. PUSHMI_TEMPLATE(class Data, class DVF)
  374. (requires PUSHMI_EXP(
  375. lazy::True<> PUSHMI_AND
  376. lazy::FlowReceiverDataArg<Data>))
  377. auto operator()(Data d, DVF nf) const {
  378. return flow_receiver<Data, DVF, passDEF, passDDF, passDStrtF>{
  379. std::move(d), std::move(nf)};
  380. }
  381. PUSHMI_TEMPLATE(class Data, class... DEFN)
  382. (requires PUSHMI_EXP(
  383. lazy::FlowReceiverDataArg<Data>))
  384. auto operator()(Data d, on_error_fn<DEFN...> ef) const {
  385. return flow_receiver<Data, passDVF, on_error_fn<DEFN...>, passDDF, passDStrtF>{
  386. std::move(d), std::move(ef)};
  387. }
  388. PUSHMI_TEMPLATE(class Data, class... DDFN)
  389. (requires PUSHMI_EXP(
  390. lazy::FlowReceiverDataArg<Data>))
  391. auto operator()(Data d, on_done_fn<DDFN...> df) const {
  392. return flow_receiver<Data, passDVF, passDEF, on_done_fn<DDFN...>, passDStrtF>{
  393. std::move(d), std::move(df)};
  394. }
  395. PUSHMI_TEMPLATE(class Data, class DVF, class DEF)
  396. (requires PUSHMI_EXP(
  397. lazy::FlowReceiverDataArg<Data>
  398. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  399. not lazy::Invocable<DEF&, Data&>)))
  400. auto operator()(Data d, DVF nf, DEF ef) const {
  401. return flow_receiver<Data, DVF, DEF, passDDF, passDStrtF>{std::move(d), std::move(nf), std::move(ef)};
  402. }
  403. PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
  404. (requires PUSHMI_EXP(
  405. lazy::FlowReceiverDataArg<Data> PUSHMI_AND
  406. lazy::Invocable<DDF&, Data&>))
  407. auto operator()(Data d, DEF ef, DDF df) const {
  408. return flow_receiver<Data, passDVF, DEF, DDF, passDStrtF>{
  409. std::move(d), std::move(ef), std::move(df)};
  410. }
  411. PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF)
  412. (requires PUSHMI_EXP(
  413. lazy::FlowReceiverDataArg<Data> PUSHMI_AND
  414. lazy::Invocable<DDF&, Data&>))
  415. auto operator()(Data d, DVF nf, DEF ef, DDF df) const {
  416. return flow_receiver<Data, DVF, DEF, DDF, passDStrtF>{std::move(d),
  417. std::move(nf), std::move(ef), std::move(df)};
  418. }
  419. PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF, class DStrtF)
  420. (requires PUSHMI_EXP(
  421. lazy::FlowReceiverDataArg<Data> PUSHMI_AND
  422. lazy::Invocable<DDF&, Data&>))
  423. auto operator()(Data d, DVF nf, DEF ef, DDF df, DStrtF strtf) const {
  424. return flow_receiver<Data, DVF, DEF, DDF, DStrtF>{std::move(d),
  425. std::move(nf), std::move(ef), std::move(df), std::move(strtf)};
  426. }
  427. } const make_flow_receiver {};
  428. ////////////////////////////////////////////////////////////////////////////////
  429. // deduction guides
  430. #if __cpp_deduction_guides >= 201703
  431. flow_receiver() -> flow_receiver<>;
  432. PUSHMI_TEMPLATE(class VF)
  433. (requires PUSHMI_EXP(
  434. lazy::True<>
  435. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  436. not lazy::FlowReceiverDataArg<VF>)))
  437. flow_receiver(VF) ->
  438. flow_receiver<VF, abortEF, ignoreDF, ignoreStrtF>;
  439. template <class... EFN>
  440. flow_receiver(on_error_fn<EFN...>) ->
  441. flow_receiver<ignoreVF, on_error_fn<EFN...>, ignoreDF, ignoreStrtF>;
  442. template <class... DFN>
  443. flow_receiver(on_done_fn<DFN...>) ->
  444. flow_receiver<ignoreVF, abortEF, on_done_fn<DFN...>, ignoreStrtF>;
  445. PUSHMI_TEMPLATE(class VF, class EF)
  446. (requires PUSHMI_EXP(
  447. lazy::True<>
  448. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  449. not lazy::FlowReceiverDataArg<VF> PUSHMI_AND
  450. not lazy::Invocable<EF&>)))
  451. flow_receiver(VF, EF) ->
  452. flow_receiver<VF, EF, ignoreDF, ignoreStrtF>;
  453. PUSHMI_TEMPLATE(class EF, class DF)
  454. (requires PUSHMI_EXP(
  455. lazy::True<> PUSHMI_AND
  456. lazy::Invocable<DF&>
  457. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  458. not lazy::FlowReceiverDataArg<EF>)))
  459. flow_receiver(EF, DF) ->
  460. flow_receiver<ignoreVF, EF, DF, ignoreStrtF>;
  461. PUSHMI_TEMPLATE(class VF, class EF, class DF)
  462. (requires PUSHMI_EXP(
  463. lazy::Invocable<DF&>
  464. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  465. not lazy::FlowReceiverDataArg<VF>)))
  466. flow_receiver(VF, EF, DF) ->
  467. flow_receiver<VF, EF, DF, ignoreStrtF>;
  468. PUSHMI_TEMPLATE(class VF, class EF, class DF, class StrtF)
  469. (requires PUSHMI_EXP(
  470. lazy::Invocable<DF&>
  471. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  472. not lazy::FlowReceiverDataArg<VF>)))
  473. flow_receiver(VF, EF, DF, StrtF) ->
  474. flow_receiver<VF, EF, DF, StrtF>;
  475. PUSHMI_TEMPLATE(class Data)
  476. (requires PUSHMI_EXP(
  477. lazy::True<> PUSHMI_AND
  478. lazy::FlowReceiverDataArg<Data>))
  479. flow_receiver(Data d) ->
  480. flow_receiver<Data, passDVF, passDEF, passDDF, passDStrtF>;
  481. PUSHMI_TEMPLATE(class Data, class DVF)
  482. (requires PUSHMI_EXP(
  483. lazy::True<> PUSHMI_AND
  484. lazy::FlowReceiverDataArg<Data>))
  485. flow_receiver(Data d, DVF nf) ->
  486. flow_receiver<Data, DVF, passDEF, passDDF, passDStrtF>;
  487. PUSHMI_TEMPLATE(class Data, class... DEFN)
  488. (requires PUSHMI_EXP(
  489. lazy::FlowReceiverDataArg<Data>))
  490. flow_receiver(Data d, on_error_fn<DEFN...>) ->
  491. flow_receiver<Data, passDVF, on_error_fn<DEFN...>, passDDF, passDStrtF>;
  492. PUSHMI_TEMPLATE(class Data, class... DDFN)
  493. (requires PUSHMI_EXP(
  494. lazy::FlowReceiverDataArg<Data>))
  495. flow_receiver(Data d, on_done_fn<DDFN...>) ->
  496. flow_receiver<Data, passDVF, passDEF, on_done_fn<DDFN...>, passDStrtF>;
  497. PUSHMI_TEMPLATE(class Data, class DDF)
  498. (requires PUSHMI_EXP(
  499. lazy::True<> PUSHMI_AND
  500. lazy::FlowReceiverDataArg<Data> PUSHMI_AND
  501. lazy::Invocable<DDF&, Data&>))
  502. flow_receiver(Data d, DDF) ->
  503. flow_receiver<Data, passDVF, passDEF, DDF, passDStrtF>;
  504. PUSHMI_TEMPLATE(class Data, class DVF, class DEF)
  505. (requires PUSHMI_EXP(
  506. lazy::FlowReceiverDataArg<Data>
  507. PUSHMI_BROKEN_SUBSUMPTION(PUSHMI_AND
  508. not lazy::Invocable<DEF&, Data&>)))
  509. flow_receiver(Data d, DVF nf, DEF ef) ->
  510. flow_receiver<Data, DVF, DEF, passDDF, passDStrtF>;
  511. PUSHMI_TEMPLATE(class Data, class DEF, class DDF)
  512. (requires PUSHMI_EXP(
  513. lazy::FlowReceiverDataArg<Data> PUSHMI_AND
  514. lazy::Invocable<DDF&, Data&>))
  515. flow_receiver(Data d, DEF, DDF) ->
  516. flow_receiver<Data, passDVF, DEF, DDF, passDStrtF>;
  517. PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF)
  518. (requires PUSHMI_EXP(
  519. lazy::FlowReceiverDataArg<Data> PUSHMI_AND
  520. lazy::Invocable<DDF&, Data&>))
  521. flow_receiver(Data d, DVF nf, DEF ef, DDF df) ->
  522. flow_receiver<Data, DVF, DEF, DDF, passDStrtF>;
  523. PUSHMI_TEMPLATE(class Data, class DVF, class DEF, class DDF, class DStrtF)
  524. (requires PUSHMI_EXP(
  525. lazy::FlowReceiverDataArg<Data> PUSHMI_AND
  526. lazy::Invocable<DDF&, Data&> ))
  527. flow_receiver(Data d, DVF nf, DEF ef, DDF df, DStrtF strtf) ->
  528. flow_receiver<Data, DVF, DEF, DDF, DStrtF>;
  529. #endif
  530. template<>
  531. struct construct_deduced<flow_receiver> : make_flow_receiver_fn {};
  532. } // namespace pushmi