proxygen
executor.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 
18 #include <chrono>
19 #include <functional>
20 
26 
27 namespace folly {
28 namespace pushmi {
29 namespace detail {
30 template <class T, template <class...> class C>
31 using not_is_t = std::enable_if_t<!is_v<std::decay_t<T>, C>, std::decay_t<T>>;
32 } // namespace detail
33 
34 //
35 // define types for executors
36 
37 namespace detail {
38 template <class T>
40 } // namespace detail
41 
42 template<class E>
44 private:
46  void* pobj_;
47  struct vtable {
48  void (*submit_)(void*, void*);
49  } const *vptr_;
50  template <class T>
52 public:
54 
55  any_executor_ref() = delete;
56  any_executor_ref(const any_executor_ref&) = default;
57 
58  PUSHMI_TEMPLATE (class Wrapped)
59  (requires Sender<wrapped_t<Wrapped>, is_executor<>, is_single<>>)
60  // (requires SenderTo<wrapped_t<Wrapped>, any_receiver<E, This>>)
61  any_executor_ref(Wrapped& w) {
62  // This can't be a requirement because it asks if submit(w, any_receiver<E,T>)
63  // is well-formed (where T is an alias for any_executor_ref). If w
64  // has a submit that is constrained with SingleReceiver<any_receiver<E,T>, T'&, E'>, that
65  // will ask whether value(any_receiver<E,T>, T'&) is well-formed. And *that* will
66  // ask whether T'& is convertible to T. That brings us right back to this
67  // constructor. Constraint recursion!
68  static_assert(
69  SenderTo<Wrapped, any_receiver<E,This>>,
70  "Expecting to be passed a Sender that can send to a SingleReceiver"
71  " that accpets a value of type This and an error of type E");
72  struct s {
73  static void submit(void* pobj, void* s) {
75  *static_cast<Wrapped*>(pobj),
76  std::move(*static_cast<any_receiver<E, This>*>(s)));
77  }
78  };
79  static const vtable vtbl{s::submit};
80  pobj_ = std::addressof(w);
81  vptr_ = &vtbl;
82  }
83  any_executor_ref executor() { return *this; }
84  template<class SingleReceiver>
85  void submit(SingleReceiver&& sa) {
86  // static_assert(
87  // ConvertibleTo<SingleReceiver, any_receiver<E, This>>,
88  // "requires any_receiver<E, any_executor_ref<E>>");
89  any_receiver<E, This> s{(SingleReceiver&&) sa};
90  vptr_->submit_(pobj_, &s);
91  }
92 };
93 
95 // make_any_executor_ref
96 template <
97  class E = std::exception_ptr>
99  return any_executor_ref<E>{};
100 }
101 
103  class E = std::exception_ptr,
104  class Wrapped)
105  (requires Sender<detail::not_any_executor_ref_t<Wrapped>, is_executor<>, is_single<>>)
106 auto make_any_executor_ref(Wrapped& w) {
107  return any_executor_ref<E>{w};
108 }
109 
111 // deduction guides
112 #if __cpp_deduction_guides >= 201703
113 any_executor_ref() ->
115  std::exception_ptr>;
116 
117 PUSHMI_TEMPLATE (class Wrapped)
118  (requires Sender<detail::not_any_executor_ref_t<Wrapped>, is_executor<>, is_single<>>)
119 any_executor_ref(Wrapped&) ->
121  std::exception_ptr>;
122 #endif
123 
124 namespace detail {
125 template<class E>
126 using any_executor_base =
128 
129 template<class T, class E>
130 using not_any_executor =
131  std::enable_if_t<
132  !std::is_base_of<any_executor_base<E>, std::decay_t<T>>::value,
133  std::decay_t<T>>;
134 } // namespace detail
135 
136 template <class E>
138  constexpr any_executor() = default;
139  using properties = property_set<is_sender<>, is_executor<>, is_single<>>;
141 };
142 
144 // make_any_executor
145 template <
146  class E = std::exception_ptr>
148  return any_executor<E>{};
149 }
150 
152  class E = std::exception_ptr,
153  class Wrapped)
154  (requires SenderTo<
157 auto make_any_executor(Wrapped w) -> any_executor<E> {
158  return any_executor<E>{std::move(w)};
159 }
160 
162 // deduction guides
163 #if __cpp_deduction_guides >= 201703
164 any_executor() ->
165  any_executor<
166  std::exception_ptr>;
167 
168 PUSHMI_TEMPLATE(class Wrapped)
169  (requires SenderTo<
171  Wrapped,
172  std::exception_ptr>,
173  any_receiver<
174  std::exception_ptr,
176  std::exception_ptr>>>)
177 any_executor(Wrapped) ->
178  any_executor<
179  std::exception_ptr>;
180 #endif
181 
182 
183 //
184 // define types for constrained executors
185 
186 namespace detail {
187 template <class T>
189 } // namespace detail
190 
191 template<class E, class CV>
193 private:
195  void* pobj_;
196  struct vtable {
197  CV (*top_)(void*);
198  void (*submit_)(void*, CV, void*);
199  } const *vptr_;
200  template <class T>
202 public:
203  using properties = property_set<is_constrained<>, is_executor<>, is_single<>>;
204 
205  any_constrained_executor_ref() = delete;
207 
208  PUSHMI_TEMPLATE (class Wrapped)
209  (requires ConstrainedSender<wrapped_t<Wrapped>, is_single<>>)
210  // (requires ConstrainedSenderTo<wrapped_t<Wrapped>, any_receiver<E,This>>)
212  // This can't be a requirement because it asks if submit(w, top(w), any_receiver<E,T>)
213  // is well-formed (where T is an alias for any_constrained_executor_ref). If w
214  // has a submit that is constrained with ReceiveValue<any_receiver<E,T>, T'&>, that
215  // will ask whether value(any_receiver<E,T>, T'&) is well-formed. And *that* will
216  // ask whether T'& is convertible to T. That brings us right back to this
217  // constructor. Constraint recursion!
218  static_assert(
219  ConstrainedSenderTo<Wrapped, any_receiver<E,This>>,
220  "Expecting to be passed a ConstrainedSender that can send to a SingleReceiver"
221  " that accpets a value of type This and an error of type E");
222  struct s {
223  static CV top(void* pobj) {
224  return ::folly::pushmi::top(*static_cast<Wrapped*>(pobj));
225  }
226  static void submit(void* pobj, CV cv, void* s) {
228  *static_cast<Wrapped*>(pobj),
229  cv,
230  std::move(*static_cast<any_receiver<E, This>*>(s)));
231  }
232  };
233  static const vtable vtbl{s::top, s::submit};
234  pobj_ = std::addressof(w);
235  vptr_ = &vtbl;
236  }
237  CV top() {
238  return vptr_->top_(pobj_);
239  }
241  template<class SingleReceiver>
242  void submit(CV cv, SingleReceiver&& sa) {
243  // static_assert(
244  // ConvertibleTo<SingleReceiver, any_receiver<E, This>>,
245  // "requires any_receiver<E, any_constrained_executor_ref<E, TP>>");
246  any_receiver<E, This> s{(SingleReceiver&&) sa};
247  vptr_->submit_(pobj_, cv, &s);
248  }
249 };
250 
252 // make_any_constrained_executor_ref
253 template <
254  class E = std::exception_ptr,
255  class CV = std::ptrdiff_t>
258 }
259 
261  class E = std::exception_ptr,
262  class Wrapped)
263  (requires ConstrainedSender<detail::not_any_constrained_executor_ref_t<Wrapped>, is_single<>>)
264 auto make_any_constrained_executor_ref(Wrapped& w) {
266 }
267 
269 // deduction guides
270 #if __cpp_deduction_guides >= 201703
273  std::exception_ptr,
274  std::ptrdiff_t>;
275 
276 PUSHMI_TEMPLATE (class Wrapped)
277  (requires ConstrainedSender<detail::not_any_constrained_executor_ref_t<Wrapped>, is_single<>>)
278 any_constrained_executor_ref(Wrapped&) ->
280  std::exception_ptr,
281  constraint_t<Wrapped>>;
282 #endif
283 
284 namespace detail {
285 template<class E, class CV>
288 
289 template<class T, class E, class CV>
291  std::enable_if_t<
292  !std::is_base_of<any_constrained_executor_base<E, CV>, std::decay_t<T>>::value,
293  std::decay_t<T>>;
294 } // namespace detail
295 
296 template <class E, class CV>
298  using properties = property_set<is_constrained<>, is_executor<>, is_single<>>;
299  constexpr any_constrained_executor() = default;
301 };
302 
304 // make_any_constrained_executor
305 template <
306  class E = std::exception_ptr,
307  class CV = std::ptrdiff_t>
310 }
311 
313  class E = std::exception_ptr,
314  class Wrapped)
315  (requires ConstrainedSenderTo<
320 }
321 
323 // deduction guides
324 #if __cpp_deduction_guides >= 201703
327  std::exception_ptr,
328  std::ptrdiff_t>;
329 
330 PUSHMI_TEMPLATE(class Wrapped)
331  (requires ConstrainedSenderTo<
333  Wrapped,
334  std::exception_ptr,
335  constraint_t<Wrapped>>,
336  any_receiver<
337  std::exception_ptr,
339  std::exception_ptr,
340  constraint_t<Wrapped>>>>)
341 any_constrained_executor(Wrapped) ->
343  std::exception_ptr,
344  constraint_t<Wrapped>>;
345 #endif
346 
347 //
348 // define types for time executors
349 
350 namespace detail {
351 template <class T>
353 } // namespace detail
354 
355 template<class E, class TP>
357 private:
359  void* pobj_;
360  struct vtable {
361  TP (*now_)(void*);
362  void (*submit_)(void*, TP, void*);
363  } const *vptr_;
364  template <class T>
366 public:
367  using properties = property_set<is_time<>, is_executor<>, is_single<>>;
368 
369  any_time_executor_ref() = delete;
371 
372  PUSHMI_TEMPLATE (class Wrapped)
373  (requires TimeSender<wrapped_t<Wrapped>, is_single<>>)
374  // (requires TimeSenderTo<wrapped_t<Wrapped>, receiver<E, This>>)
375  any_time_executor_ref(Wrapped& w) {
376  // This can't be a requirement because it asks if submit(w, now(w), any_receiver<E, T>)
377  // is well-formed (where T is an alias for any_time_executor_ref). If w
378  // has a submit that is constrained with ReceiverValue<any_receiver<E, T>, T'&>, that
379  // will ask whether value(any_receiver<E, T>, T'&) is well-formed. And *that* will
380  // ask whether T'& is convertible to T. That brings us right back to this
381  // constructor. Constraint recursion!
382  static_assert(
383  TimeSenderTo<Wrapped, any_receiver<E, This>>,
384  "Expecting to be passed a TimeSender that can send to a SingleReceiver"
385  " that accpets a value of type This and an error of type E");
386  struct s {
387  static TP now(void* pobj) {
388  return ::folly::pushmi::now(*static_cast<Wrapped*>(pobj));
389  }
390  static void submit(void* pobj, TP tp, void* s) {
392  *static_cast<Wrapped*>(pobj),
393  tp,
394  std::move(*static_cast<any_receiver<E, This>*>(s)));
395  }
396  };
397  static const vtable vtbl{s::now, s::submit};
398  pobj_ = std::addressof(w);
399  vptr_ = &vtbl;
400  }
401  std::chrono::system_clock::time_point top() {
402  return vptr_->now_(pobj_);
403  }
404  any_time_executor_ref executor() { return *this; }
405  template<class SingleReceiver>
406  void submit(TP tp, SingleReceiver&& sa) {
407  // static_assert(
408  // ConvertibleTo<SingleReceiver, any_receiver<E, This>>,
409  // "requires any_receiver<E, any_time_executor_ref<E, TP>>");
410  any_receiver<E, This> s{(SingleReceiver&&) sa};
411  vptr_->submit_(pobj_, tp, &s);
412  }
413 };
414 
416 // make_any_time_executor_ref
417 template <
418  class E = std::exception_ptr,
419  class TP = std::chrono::system_clock::time_point>
422 }
423 
425  class E = std::exception_ptr,
426  class Wrapped)
427  (requires TimeSender<detail::not_any_time_executor_ref_t<Wrapped>, is_single<>>)
428 auto make_any_time_executor_ref(Wrapped& w) {
430 }
431 
433 // deduction guides
434 #if __cpp_deduction_guides >= 201703
437  std::exception_ptr,
438  std::chrono::system_clock::time_point>;
439 
440 PUSHMI_TEMPLATE (class Wrapped)
441  (requires TimeSender<detail::not_any_time_executor_ref_t<Wrapped>, is_single<>>)
442 any_time_executor_ref(Wrapped&) ->
444  std::exception_ptr,
445  time_point_t<Wrapped>>;
446 #endif
447 
448 namespace detail {
449 template<class E, class TP>
452 
453 template<class T, class E, class TP>
454 using not_any_time_executor =
455  std::enable_if_t<
456  !std::is_base_of<any_time_executor_base<E, TP>, std::decay_t<T>>::value,
457  std::decay_t<T>>;
458 } // namespace detail
459 
460 template <class E, class TP>
462  using properties = property_set<is_time<>, is_executor<>, is_single<>>;
463  constexpr any_time_executor() = default;
465 };
466 
468 // make_any_time_executor
469 template <
470  class E = std::exception_ptr,
471  class TP = std::chrono::system_clock::time_point>
473  return any_time_executor<E, TP>{};
474 }
475 
477  class E = std::exception_ptr,
478  class Wrapped)
479  (requires TimeSenderTo<
484 }
485 
487 // deduction guides
488 #if __cpp_deduction_guides >= 201703
491  std::exception_ptr,
492  std::chrono::system_clock::time_point>;
493 
494 PUSHMI_TEMPLATE(class Wrapped)
495  (requires TimeSenderTo<
497  Wrapped,
498  std::exception_ptr,
499  time_point_t<Wrapped>>,
500  any_receiver<
501  std::exception_ptr,
503  std::exception_ptr,
504  time_point_t<Wrapped>>>>)
505 any_time_executor(Wrapped) ->
507  std::exception_ptr,
508  time_point_t<Wrapped>>;
509 #endif
510 
511 } // namespace pushmi
512 } // namespace folly
auto make_any_executor_ref()
Definition: executor.h:98
detail::not_any_executor_ref_t< T > wrapped_t
Definition: executor.h:51
any_constrained_executor_ref executor()
Definition: executor.h:240
auto make_any_time_executor_ref()
Definition: executor.h:420
requires Sender< wrapped_t< Wrapped >, is_executor<>, is_single<> > any_executor_ref(Wrapped &w)
Definition: executor.h:61
not_is_t< T, any_time_executor_ref > not_any_time_executor_ref_t
Definition: executor.h:352
std::chrono::steady_clock::time_point now()
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
std::enable_if_t<!is_v< std::decay_t< T >, C >, std::decay_t< T >> not_is_t
Definition: executor.h:31
any_constrained_single_sender< E, CV, any_constrained_executor_ref< E, CV >> any_constrained_executor_base
Definition: executor.h:287
folly::std T
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
detail::not_any_time_executor_ref_t< T > wrapped_t
Definition: executor.h:365
any_time_single_sender< E, TP, any_time_executor_ref< E, TP >> any_time_executor_base
Definition: executor.h:451
requires TimeSender< wrapped_t< Wrapped >, is_single<> > any_time_executor_ref(Wrapped &w)
Definition: executor.h:375
void submit(SingleReceiver &&sa)
Definition: executor.h:85
auto make_any_time_executor() -> any_time_executor< E, TP >
Definition: executor.h:472
void submit(TP tp, SingleReceiver &&sa)
Definition: executor.h:406
not_is_t< T, any_constrained_executor_ref > not_any_constrained_executor_ref_t
Definition: executor.h:188
auto make_any_constrained_executor() -> any_constrained_executor< E, CV >
Definition: executor.h:308
requires requires(::folly::pushmi::invoke(std::declval< F >(), std::get< Is >(std::declval< Tuple >())...))) const expr decltype(auto) apply_impl(F &&f
requires ConstrainedSender< wrapped_t< Wrapped >, is_single<> > any_constrained_executor_ref(Wrapped &w)
Definition: executor.h:211
std::chrono::system_clock::time_point top()
Definition: executor.h:401
#define C(name, bit)
Definition: CpuId.h:204
auto make_any_constrained_executor_ref()
Definition: executor.h:256
PUSHMI_INLINE_VAR constexpr __adl::get_top_fn now
PUSHMI_INLINE_VAR constexpr __adl::get_top_fn top
detail::not_any_constrained_executor_ref_t< T > wrapped_t
Definition: executor.h:201
void submit(CV cv, SingleReceiver &&sa)
Definition: executor.h:242
any_time_executor_ref executor()
Definition: executor.h:404
static set< string > s
uint64_t value(const typename LockFreeRingBuffer< T, Atom >::Cursor &rbcursor)
any_executor_ref executor()
Definition: executor.h:83
std::enable_if_t< !std::is_base_of< any_executor_base< E >, std::decay_t< T >>::value, std::decay_t< T >> not_any_executor
Definition: executor.h:133
PUSHMI_INLINE_VAR constexpr __adl::do_submit_fn submit
PUSHMI_TEMPLATE(class In, class Out, bool SenderRequires, bool SingleSenderRequires, bool TimeSingleSenderRequires)(requires Sender< In > &&Receiver< Out >) constexpr bool sender_requires_from()
not_is_t< T, any_executor_ref > not_any_executor_ref_t
Definition: executor.h:39
std::enable_if_t< !std::is_base_of< any_time_executor_base< E, TP >, std::decay_t< T >>::value, std::decay_t< T >> not_any_time_executor
Definition: executor.h:457
auto make_any_executor() -> any_executor< E >
Definition: executor.h:147
std::enable_if_t< !std::is_base_of< any_constrained_executor_base< E, CV >, std::decay_t< T >>::value, std::decay_t< T >> not_any_constrained_executor
Definition: executor.h:293
any_single_sender< E, any_executor_ref< E >> any_executor_base
Definition: executor.h:127