on.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  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/executor.h>
  18. #include <folly/experimental/pushmi/o/extension_operators.h>
  19. #include <folly/experimental/pushmi/piping.h>
  20. namespace pushmi {
  21. namespace detail {
  22. struct on_fn {
  23. private:
  24. template <class In, class Out>
  25. struct on_value_impl {
  26. In in_;
  27. Out out_;
  28. void operator()(any) {
  29. ::pushmi::submit(in_, std::move(out_));
  30. }
  31. };
  32. template <class In, class ExecutorFactory>
  33. struct out_impl {
  34. ExecutorFactory ef_;
  35. PUSHMI_TEMPLATE(class Out)
  36. (requires SenderTo<In, Out>)
  37. void operator()(In& in, Out out) const {
  38. auto exec = ef_();
  39. ::pushmi::submit(
  40. exec,
  41. ::pushmi::make_receiver(on_value_impl<In, Out>{in, std::move(out)}));
  42. }
  43. };
  44. template <class In, class TP, class Out>
  45. struct time_on_value_impl {
  46. In in_;
  47. TP at_;
  48. Out out_;
  49. void operator()(any) {
  50. ::pushmi::submit(in_, at_, std::move(out_));
  51. }
  52. };
  53. template <class In, class ExecutorFactory>
  54. struct time_out_impl {
  55. ExecutorFactory ef_;
  56. PUSHMI_TEMPLATE(class TP, class Out)
  57. (requires TimeSenderTo<In, Out>)
  58. void operator()(In& in, TP at, Out out) const {
  59. auto exec = ef_();
  60. ::pushmi::submit(
  61. exec,
  62. at,
  63. ::pushmi::make_receiver(
  64. time_on_value_impl<In, TP, Out>{in, at, std::move(out)}));
  65. }
  66. };
  67. template <class ExecutorFactory>
  68. struct in_impl {
  69. ExecutorFactory ef_;
  70. PUSHMI_TEMPLATE(class In)
  71. (requires Sender<In>)
  72. auto operator()(In in) const {
  73. return ::pushmi::detail::sender_from(
  74. std::move(in),
  75. detail::submit_transform_out<In>(
  76. out_impl<In, ExecutorFactory>{ef_},
  77. time_out_impl<In, ExecutorFactory>{ef_}));
  78. }
  79. };
  80. public:
  81. PUSHMI_TEMPLATE(class ExecutorFactory)
  82. (requires Invocable<ExecutorFactory&>&&
  83. Executor<invoke_result_t<ExecutorFactory&>>)
  84. auto operator()(ExecutorFactory ef) const {
  85. return in_impl<ExecutorFactory>{std::move(ef)};
  86. }
  87. };
  88. } // namespace detail
  89. namespace operators {
  90. PUSHMI_INLINE_VAR constexpr detail::on_fn on{};
  91. } // namespace operators
  92. } // namespace pushmi