proxygen
constrained_single_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 CV, class... VN>
27  union data {
28  void* pobj_ = nullptr;
29  char buffer_[sizeof(std::promise<int>)]; // 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*) {}
38  static CV s_top(data&) { return CV{}; }
40  static void s_submit(data&, CV, any_receiver<E, VN...>) {}
41  void (*op_)(data&, data*) = vtable::s_op;
42  CV (*top_)(data&) = vtable::s_top;
44  void (*submit_)(data&, CV, any_receiver<E, VN...>) = vtable::s_submit;
45  };
46  static constexpr vtable const noop_ {};
47  vtable const* vptr_ = &noop_;
48  template <class Wrapped>
51  struct s {
52  static void op(data& src, data* dst) {
53  if (dst)
54  dst->pobj_ = std::exchange(src.pobj_, nullptr);
55  delete static_cast<Wrapped const*>(src.pobj_);
56  }
57  static CV top(data& src) {
58  return ::folly::pushmi::top(*static_cast<Wrapped*>(src.pobj_));
59  }
62  executor(*static_cast<Wrapped*>(src.pobj_))};
63  }
64  static void submit(data& src, CV at, any_receiver<E, VN...> out) {
66  *static_cast<Wrapped*>(src.pobj_), std::move(at), std::move(out));
67  }
68  };
69  static const vtable vtbl{s::op, s::top, s::executor, s::submit};
70  data_.pobj_ = new Wrapped(std::move(obj));
71  vptr_ = &vtbl;
72  }
73  template <class Wrapped>
76  struct s {
77  static void op(data& src, data* dst) {
78  if (dst)
79  new (dst->buffer_) Wrapped(
80  std::move(*static_cast<Wrapped*>((void*)src.buffer_)));
81  static_cast<Wrapped const*>((void*)src.buffer_)->~Wrapped();
82  }
83  static CV top(data& src) {
84  return ::folly::pushmi::top(*static_cast<Wrapped*>((void*)src.buffer_));
85  }
88  *static_cast<Wrapped*>((void*)src.buffer_))};
89  }
90  static void submit(data& src, CV cv, any_receiver<E, VN...> out) {
92  *static_cast<Wrapped*>((void*)src.buffer_),
93  std::move(cv),
94  std::move(out));
95  }
96  };
97  static const vtable vtbl{s::op, s::top, s::executor, s::submit};
98  new (data_.buffer_) Wrapped(std::move(obj));
99  vptr_ = &vtbl;
100  }
101  template <class T, class U = std::decay_t<T>>
102  using wrapped_t =
104 
105  public:
107 
108  any_constrained_single_sender() = default;
111  that.vptr_->op_(that.data_, &data_);
112  std::swap(that.vptr_, vptr_);
113  }
114  PUSHMI_TEMPLATE (class Wrapped)
115  (requires ConstrainedSenderTo<wrapped_t<Wrapped>, any_receiver<E, VN...>>)
116  explicit any_constrained_single_sender(Wrapped obj) noexcept(insitu<Wrapped>())
118  }
120  vptr_->op_(data_, nullptr);
121  }
124  new ((void*)this) any_constrained_single_sender(std::move(that));
125  return *this;
126  }
127  CV top() {
128  return vptr_->top_(data_);
129  }
131  return vptr_->executor_(data_);
132  }
133  void submit(CV at, any_receiver<E, VN...> out) {
134  vptr_->submit_(data_, std::move(at), std::move(out));
135  }
136 };
137 
138 // Class static definitions:
139 template <class E, class CV, class... VN>
140 constexpr typename any_constrained_single_sender<E, CV, VN...>::vtable const
142 
143 template<class SF, class ZF, class EXF>
144  // (requires Invocable<ZF&> && Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
145 class constrained_single_sender<SF, ZF, EXF> {
146  SF sf_;
147  ZF zf_;
148  EXF exf_;
149 
150  public:
152 
153  constexpr constrained_single_sender() = default;
154  constexpr explicit constrained_single_sender(SF sf)
155  : sf_(std::move(sf)) {}
156  constexpr constrained_single_sender(SF sf, EXF exf)
157  : sf_(std::move(sf)), exf_(std::move(exf)) {}
158  constexpr constrained_single_sender(SF sf, EXF exf, ZF zf)
159  : sf_(std::move(sf)), zf_(std::move(zf)), exf_(std::move(exf)) {}
160 
161  auto top() {
162  return zf_();
163  }
164  auto executor() { return exf_(); }
165  PUSHMI_TEMPLATE(class CV, class Out)
166  (requires Regular<CV> && Receiver<Out> &&
167  Invocable<SF&, CV, Out>)
168  void submit(CV cv, Out out) {
169  sf_(std::move(cv), std::move(out));
170  }
171 };
172 
173 template <PUSHMI_TYPE_CONSTRAINT(ConstrainedSender<is_single<>>) Data, class DSF, class DZF, class DEXF>
174 #if __cpp_concepts
175  requires Invocable<DZF&, Data&> && Invocable<DEXF&, Data&>
176 #endif
177 class constrained_single_sender<Data, DSF, DZF, DEXF> {
179  DSF sf_;
180  DZF zf_;
181  DEXF exf_;
182 
183  public:
185 
186  constexpr constrained_single_sender() = default;
187  constexpr explicit constrained_single_sender(Data data)
188  : data_(std::move(data)) {}
189  constexpr constrained_single_sender(Data data, DSF sf, DEXF exf = DEXF{})
190  : data_(std::move(data)), sf_(std::move(sf)), exf_(std::move(exf)) {}
191  constexpr constrained_single_sender(Data data, DSF sf, DEXF exf, DZF zf)
192  : data_(std::move(data)), sf_(std::move(sf)), zf_(std::move(zf)), exf_(std::move(exf)) {}
193 
194  auto top() {
195  return zf_(data_);
196  }
197  auto executor() { return exf_(data_); }
198  PUSHMI_TEMPLATE(class CV, class Out)
199  (requires Regular<CV> && Receiver<Out> &&
200  Invocable<DSF&, Data&, CV, Out>)
201  void submit(CV cv, Out out) {
202  sf_(data_, std::move(cv), std::move(out));
203  }
204 };
205 
206 template <>
208  : public constrained_single_sender<ignoreSF, priorityZeroF, inlineConstrainedEXF> {
209 public:
210  constrained_single_sender() = default;
211 };
212 
214 // make_constrained_single_sender
216  inline auto operator()() const {
218  }
219  PUSHMI_TEMPLATE(class SF)
220  (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
221  auto operator()(SF sf) const {
223  }
224  PUSHMI_TEMPLATE (class SF, class EXF)
225  (requires Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
226  auto operator()(SF sf, EXF exf) const {
228  }
229  PUSHMI_TEMPLATE (class SF, class ZF, class EXF)
230  (requires Invocable<ZF&> && Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
231  auto operator()(SF sf, EXF exf, ZF zf) const {
233  }
234  PUSHMI_TEMPLATE (class Data)
235  (requires ConstrainedSender<Data, is_single<>>)
236  auto operator()(Data d) const {
238  }
239  PUSHMI_TEMPLATE (class Data, class DSF)
240  (requires ConstrainedSender<Data, is_single<>>)
241  auto operator()(Data d, DSF sf) const {
243  }
244  PUSHMI_TEMPLATE (class Data, class DSF, class DEXF)
245  (requires ConstrainedSender<Data, is_single<>> && Invocable<DEXF&, Data&>)
246  auto operator()(Data d, DSF sf, DEXF exf) const {
248  std::move(exf)};
249  }
250  PUSHMI_TEMPLATE (class Data, class DSF, class DZF, class DEXF)
251  (requires ConstrainedSender<Data, is_single<>> && Invocable<DZF&, Data&> && Invocable<DEXF&, Data&>)
252  auto operator()(Data d, DSF sf, DEXF exf, DZF zf) const {
254  std::move(exf), std::move(zf)};
255  }
257 
259 // deduction guides
260 #if __cpp_deduction_guides >= 201703
262 
263 PUSHMI_TEMPLATE(class SF)
264  (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
266 
267 PUSHMI_TEMPLATE (class SF, class EXF)
268  (requires Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
270 
271 PUSHMI_TEMPLATE (class SF, class ZF, class EXF)
272  (requires Invocable<ZF&> && Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
274 
275 PUSHMI_TEMPLATE (class Data, class DSF)
276  (requires ConstrainedSender<Data, is_single<>>)
278 
279 PUSHMI_TEMPLATE (class Data, class DSF, class DEXF)
280  (requires ConstrainedSender<Data, is_single<>> && Invocable<DEXF&, Data&>)
282 
283 PUSHMI_TEMPLATE (class Data, class DSF, class DZF, class DEXF)
284  (requires ConstrainedSender<Data, is_single<>> && Invocable<DZF&, Data&> && Invocable<DEXF&, Data&>)
286 #endif
287 
288 template<>
291 
292 } // namespace pushmi
293 } // namespace folly
std::true_type True
Definition: TypeList.h:82
constexpr constrained_single_sender(Data data, DSF sf, DEXF exf, DZF zf)
constexpr detail::Map< Move > move
Definition: Base-inl.h:2567
STL namespace.
any_constrained_single_sender(Wrapped obj, std::true_type) noexcept
constexpr constrained_single_sender(Data data, DSF sf, DEXF exf=DEXF{})
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
static any_constrained_executor< E, CV > s_executor(data &)
requires E e noexcept(noexcept(s.error(std::move(e))))
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_constrained_single_sender >::value, U > wrapped_t
any_constrained_single_sender(Wrapped obj, std::false_type)
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
union folly::pushmi::any_constrained_single_sender::data data_
any_constrained_single_sender & operator=(any_constrained_single_sender &&that) noexcept
static void s_submit(data &, CV, any_receiver< E, VN... >)
static const char *const value
Definition: Conv.cpp:50
#define PUSHMI_INLINE_VAR
Definition: concept_def.h:60
PUSHMI_INLINE_VAR constexpr struct folly::pushmi::make_constrained_single_sender_fn make_constrained_single_sender
std::integral_constant< bool, B > bool_
Definition: concept_def.h:443
void submit(CV at, any_receiver< E, VN... > out)
requires requires(detail::apply_impl(std::declval< F >(), std::declval< Tuple >(), detail::tupidxs< Tuple >{}))) const expr decltype(auto) apply(F &&f
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
PUSHMI_INLINE_VAR constexpr __adl::get_top_fn top
requires Regular< CV > &&Receiver< Out > &&Invocable< DSF &, Data &, CV, Out > void submit(CV cv, Out out)
static set< string > s
const
Definition: upload.py:398
bool_constant< false > false_type
Definition: gtest-port.h:2209
requires Regular< CV > &&Receiver< Out > &&Invocable< SF &, CV, Out > void submit(CV cv, Out out)
requires ConstrainedSenderTo< wrapped_t< Wrapped >, any_receiver< E, VN... > > any_constrained_single_sender(Wrapped obj) noexcept(insitu< Wrapped >())
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
property_set_insert_t< properties_t< Data >, property_set< is_single<>>> properties
#define PUSHMI_BROKEN_SUBSUMPTION(...)
Definition: concept_def.h:419
any_constrained_single_sender(any_constrained_single_sender &&that) noexcept