proxygen
many_sender.h
Go to the documentation of this file.
1 /*
2  * Copyright 2018-present Facebook, Inc.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #pragma once
17 
21 
22 namespace folly {
23 namespace pushmi {
24 
25 template <class E, class... VN>
26 class any_many_sender {
27  union data {
28  void* pobj_ = nullptr;
29  char buffer_[sizeof(std::tuple<VN...>)]; // can hold a V in-situ
30  } data_{};
31  template <class Wrapped>
32  static constexpr bool insitu() {
33  return sizeof(Wrapped) <= sizeof(data::buffer_) &&
35  }
36  struct vtable {
37  static void s_op(data&, data*) {}
39  return {};
40  }
42  void (*op_)(data&, data*) = vtable::s_op;
44  void (*submit_)(data&, any_receiver<E, VN...>) = vtable::s_submit;
45  };
46  static constexpr vtable const noop_{};
47  vtable const* vptr_ = &noop_;
48  template <class Wrapped>
50  struct s {
51  static void op(data& src, data* dst) {
52  if (dst)
53  dst->pobj_ = std::exchange(src.pobj_, nullptr);
54  delete static_cast<Wrapped const*>(src.pobj_);
55  }
56  static any_executor<E> executor(data& src) {
57  return any_executor<E>{
58  ::folly::pushmi::executor(*static_cast<Wrapped*>(src.pobj_))};
59  }
60  static void submit(data& src, any_receiver<E, VN...> out) {
62  *static_cast<Wrapped*>(src.pobj_), std::move(out));
63  }
64  };
65  static const vtable vtbl{s::op, s::executor, s::submit};
66  data_.pobj_ = new Wrapped(std::move(obj));
67  vptr_ = &vtbl;
68  }
69  template <class Wrapped>
71  struct s {
72  static void op(data& src, data* dst) {
73  if (dst)
74  new (dst->buffer_)
75  Wrapped(std::move(*static_cast<Wrapped*>((void*)src.buffer_)));
76  static_cast<Wrapped const*>((void*)src.buffer_)->~Wrapped();
77  }
78  static any_executor<E> executor(data& src) {
80  *static_cast<Wrapped*>((void*)src.buffer_))};
81  }
82  static void submit(data& src, any_receiver<E, VN...> out) {
84  *static_cast<Wrapped*>((void*)src.buffer_), std::move(out));
85  }
86  };
87  static const vtable vtbl{s::op, s::executor, s::submit};
88  new (data_.buffer_) Wrapped(std::move(obj));
89  vptr_ = &vtbl;
90  }
91  template <class T, class U = std::decay_t<T>>
92  using wrapped_t =
94 
95  public:
97 
98  any_many_sender() = default;
100  that.vptr_->op_(that.data_, &data_);
101  std::swap(that.vptr_, vptr_);
102  }
103 
104  PUSHMI_TEMPLATE(class Wrapped)
105  (requires SenderTo<
107  any_receiver<E, VN...>,
108  is_many<>>)
109  explicit any_many_sender(Wrapped obj) noexcept(insitu<Wrapped>())
112  vptr_->op_(data_, nullptr);
113  }
115  this->~any_many_sender();
116  new ((void*)this) any_many_sender(std::move(that));
117  return *this;
118  }
120  return vptr_->executor_(data_);
121  }
123  vptr_->submit_(data_, std::move(out));
124  }
125 };
126 
127 // Class static definitions:
128 template <class E, class... VN>
129 constexpr typename any_many_sender<E, VN...>::vtable const
130  any_many_sender<E, VN...>::noop_;
131 
132 template <class SF, class EXF>
133 class many_sender<SF, EXF> {
134  SF sf_;
135  EXF exf_;
136 
137  public:
139 
140  constexpr many_sender() = default;
141  constexpr explicit many_sender(SF sf) : sf_(std::move(sf)) {}
142  constexpr many_sender(SF sf, EXF exf)
143  : sf_(std::move(sf)), exf_(std::move(exf)) {}
144 
145  auto executor() {
146  return exf_();
147  }
148  PUSHMI_TEMPLATE(class Out)
149  (requires PUSHMI_EXP(lazy::Receiver<Out> PUSHMI_AND
150  lazy::Invocable<SF&, Out>))
151  void submit(Out out) {
152  sf_(std::move(out));
153  }
154 };
155 
156 template <PUSHMI_TYPE_CONSTRAINT(Sender<is_many<>>) Data, class DSF, class DEXF>
157 class many_sender<Data, DSF, DEXF> {
159  DSF sf_;
160  DEXF exf_;
161 
162  public:
166 
167  constexpr many_sender() = default;
168  constexpr explicit many_sender(Data data) : data_(std::move(data)) {}
169  constexpr many_sender(Data data, DSF sf)
170  : data_(std::move(data)), sf_(std::move(sf)) {}
171  constexpr many_sender(Data data, DSF sf, DEXF exf)
172  : data_(std::move(data)), sf_(std::move(sf)), exf_(std::move(exf)) {}
173 
174  auto executor() {
175  return exf_(data_);
176  }
177  PUSHMI_TEMPLATE(class Out)
179  lazy::Receiver<Out> PUSHMI_AND
180  lazy::Invocable<DSF&, Data&, Out>))
181  void submit(Out out) {
182  sf_(data_, std::move(out));
183  }
184 };
185 
186 template <>
187 class many_sender<> : public many_sender<ignoreSF, trampolineEXF> {
188  public:
189  many_sender() = default;
190 };
191 
193 // make_many_sender
195  inline auto operator()() const {
197  }
198  PUSHMI_TEMPLATE(class SF)
199  (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
200  auto operator()(SF sf) const {
202  }
203  PUSHMI_TEMPLATE(class SF, class EXF)
204  (requires True<> && Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
205  auto operator()(SF sf, EXF exf) const {
206  return many_sender<SF, EXF>{std::move(sf), std::move(exf)};
207  }
208  PUSHMI_TEMPLATE(class Data)
209  (requires True<> && Sender<Data, is_many<>>)
210  auto operator()(Data d) const {
212  }
213  PUSHMI_TEMPLATE(class Data, class DSF)
214  (requires Sender<Data, is_many<>>)
215  auto operator()(Data d, DSF sf) const {
217  }
218  PUSHMI_TEMPLATE(class Data, class DSF, class DEXF)
219  (requires Sender<Data, is_many<>> && Invocable<DEXF&, Data&>)
220  auto operator()(Data d, DSF sf, DEXF exf) const {
222  }
223 } const make_many_sender {};
224 
226 // deduction guides
227 #if __cpp_deduction_guides >= 201703
229 
230 PUSHMI_TEMPLATE(class SF)
231  (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
233 
234 PUSHMI_TEMPLATE(class SF, class EXF)
235  (requires True<> && Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
237 
238 PUSHMI_TEMPLATE(class Data)
239  (requires True<> && Sender<Data, is_many<>>)
241 
242 PUSHMI_TEMPLATE(class Data, class DSF)
243  (requires Sender<Data, is_many<>>)
245 
246 PUSHMI_TEMPLATE(class Data, class DSF, class DEXF)
247  (requires Sender<Data, is_many<>> && Invocable<DEXF&, Data&>)
249 #endif
250 
251 template<>
253 
254 } // namespace pushmi
255 } // namespace folly
std::true_type True
Definition: TypeList.h:82
static void s_op(data &, data *)
Definition: many_sender.h:37
any_many_sender & operator=(any_many_sender &&that) noexcept
Definition: many_sender.h:114
any_many_sender(any_many_sender &&that) noexcept
Definition: many_sender.h:99
property_set_insert_t< properties_t< Data >, property_set< is_sender<>, is_many<>>> properties
Definition: many_sender.h:165
std::enable_if_t< PropertySet< __properties_t< property_set_traits< T >>>, __properties_t< property_set_traits< T >>> properties_t
Definition: properties.h:105
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
constexpr many_sender(Data data, DSF sf)
Definition: many_sender.h:169
STL namespace.
any_many_sender(Wrapped obj, std::true_type) noexcept
Definition: many_sender.h:70
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
void submit(any_receiver< E, VN... > out)
Definition: many_sender.h:122
void(* submit_)(data &, any_receiver< E, VN... >)
Definition: many_sender.h:44
requires E e noexcept(noexcept(s.error(std::move(e))))
any_executor< E > executor()
Definition: many_sender.h:119
requires PUSHMI_EXP(lazy::Receiver< Out > PUSHMI_AND lazy::Invocable< DSF &, Data &, Out >)) void submit(Out out)
Definition: many_sender.h:178
PUSHMI_INLINE_VAR constexpr __adl::get_executor_fn executor
typename std::enable_if_t< PropertySet< PS0 > &&PropertySet< PS1 >, detail::property_set_insert< PS0, PS1 >>::type property_set_insert_t
Definition: properties.h:153
bool_constant< true > true_type
Definition: gtest-port.h:2210
std::enable_if_t<!std::is_same< U, any_many_sender >::value, U > wrapped_t
Definition: many_sender.h:93
#define PUSHMI_AND
Definition: concept_def.h:424
static constexpr vtable const noop_
Definition: many_sender.h:46
PUSHMI_INLINE_VAR constexpr struct folly::pushmi::make_many_sender_fn make_many_sender
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
static any_executor< E > s_executor(data &)
Definition: many_sender.h:38
any_many_sender(Wrapped obj, std::false_type)
Definition: many_sender.h:49
static const char *const value
Definition: Conv.cpp:50
union folly::pushmi::any_many_sender::data data_
#define PUSHMI_INLINE_VAR
Definition: concept_def.h:60
std::integral_constant< bool, B > bool_
Definition: concept_def.h:443
requires requires(detail::apply_impl(std::declval< F >(), std::declval< Tuple >(), detail::tupidxs< Tuple >{}))) const expr decltype(auto) apply(F &&f
constexpr many_sender(SF sf, EXF exf)
Definition: many_sender.h:142
T exchange(T &obj, U &&new_value)
Definition: Utility.h:120
PUSHMI_TEMPLATE(class E=std::exception_ptr, class Wrapped)(requires Sender< detail
Definition: executor.h:102
static void s_submit(data &, any_receiver< E, VN... >)
Definition: many_sender.h:41
requires SenderTo< wrapped_t< Wrapped >, any_receiver< E, VN... >, is_many<> > any_many_sender(Wrapped obj) noexcept(insitu< Wrapped >())
Definition: many_sender.h:109
static set< string > s
const
Definition: upload.py:398
bool_constant< false > false_type
Definition: gtest-port.h:2209
any_executor< E >(* executor_)(data &)
Definition: many_sender.h:43
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
static constexpr bool insitu()
Definition: many_sender.h:32
constexpr many_sender(Data data, DSF sf, DEXF exf)
Definition: many_sender.h:171
#define PUSHMI_BROKEN_SUBSUMPTION(...)
Definition: concept_def.h:419
requires PUSHMI_EXP(lazy::Receiver< Out > PUSHMI_AND lazy::Invocable< SF &, Out >)) void submit(Out out)
Definition: many_sender.h:149
char buffer_[sizeof(std::tuple< VN... >)]
Definition: many_sender.h:29