proxygen
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... VN>
26 class any_single_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  : any_single_sender() {
72  struct s {
73  static void op(data& src, data* dst) {
74  if (dst)
75  new (dst->buffer_)
76  Wrapped(std::move(*static_cast<Wrapped*>((void*)src.buffer_)));
77  static_cast<Wrapped const*>((void*)src.buffer_)->~Wrapped();
78  }
79  static any_executor<E> executor(data& src) {
81  *static_cast<Wrapped*>((void*)src.buffer_))};
82  }
83  static void submit(data& src, any_receiver<E, VN...> out) {
85  *static_cast<Wrapped*>((void*)src.buffer_), std::move(out));
86  }
87  };
88  static const vtable vtbl{s::op, s::executor, s::submit};
89  new (data_.buffer_) Wrapped(std::move(obj));
90  vptr_ = &vtbl;
91  }
92  template <class T, class U = std::decay_t<T>>
93  using wrapped_t =
95 
96  public:
98 
99  any_single_sender() = default;
101  that.vptr_->op_(that.data_, &data_);
102  std::swap(that.vptr_, vptr_);
103  }
104 
105  PUSHMI_TEMPLATE(class Wrapped)
106  (requires SenderTo<
108  any_receiver<
109  E,
110  VN...>>)explicit any_single_sender(Wrapped
111  obj) noexcept(insitu<Wrapped>())
114  vptr_->op_(data_, nullptr);
115  }
117  this->~any_single_sender();
118  new ((void*)this) any_single_sender(std::move(that));
119  return *this;
120  }
122  return vptr_->executor_(data_);
123  }
125  vptr_->submit_(data_, std::move(out));
126  }
127 };
128 
129 // Class static definitions:
130 template <class E, class... VN>
131 constexpr typename any_single_sender<E, VN...>::vtable const
132  any_single_sender<E, VN...>::noop_;
133 
134 template <class SF, class EXF>
135 class single_sender<SF, EXF> {
136  SF sf_;
137  EXF exf_;
138 
139  public:
140  using properties = property_set<is_sender<>, is_single<>>;
141 
142  constexpr single_sender() = default;
143  constexpr explicit single_sender(SF sf) : sf_(std::move(sf)) {}
144  constexpr single_sender(SF sf, EXF exf)
145  : sf_(std::move(sf)), exf_(std::move(exf)) {}
146 
147  auto executor() {
148  return exf_();
149  }
150  PUSHMI_TEMPLATE(class Out)
151  (requires PUSHMI_EXP(lazy::Receiver<Out> PUSHMI_AND
152  lazy::Invocable<SF&, Out>))
153  void submit(Out out) {
154  sf_(std::move(out));
155  }
156 };
157 
158 template <
159  PUSHMI_TYPE_CONSTRAINT(Sender<is_single<>>) Data,
160  class DSF,
161  class DEXF>
162 class single_sender<Data, DSF, DEXF> {
164  DSF sf_;
165  DEXF exf_;
166 
167  public:
170  property_set<is_sender<>, is_single<>>>;
171 
172  constexpr single_sender() = default;
173  constexpr explicit single_sender(Data data) : data_(std::move(data)) {}
174  constexpr single_sender(Data data, DSF sf)
175  : data_(std::move(data)), sf_(std::move(sf)) {}
176  constexpr single_sender(Data data, DSF sf, DEXF exf)
177  : data_(std::move(data)), sf_(std::move(sf)), exf_(std::move(exf)) {}
178 
179  auto executor() {
180  return exf_(data_);
181  }
182  PUSHMI_TEMPLATE(class Out)
184  lazy::Receiver<Out> PUSHMI_AND
185  lazy::Invocable<DSF&, Data&, Out>))
186  void submit(Out out) {
187  sf_(data_, std::move(out));
188  }
189 };
190 
191 template <>
192 class single_sender<> : public single_sender<ignoreSF, trampolineEXF> {
193  public:
194  single_sender() = default;
195 };
196 
198 // make_single_sender
200  inline auto operator()() const {
202  }
203  PUSHMI_TEMPLATE(class SF)
204  (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&&not Sender<SF>))
205  auto operator()(SF sf) const {
207  }
208  PUSHMI_TEMPLATE(class SF, class EXF)
209  (requires True<>&& Invocable<EXF&> PUSHMI_BROKEN_SUBSUMPTION(
210  &&not Sender<SF>))
211  auto operator()(SF sf, EXF exf) const {
212  return single_sender<SF, EXF>{std::move(sf), std::move(exf)};
213  }
214  PUSHMI_TEMPLATE(class Data)
215  (requires True<>&& Sender<Data, is_single<>>)
216  auto operator()(Data d) const {
218  }
219  PUSHMI_TEMPLATE(class Data, class DSF)
220  (requires Sender<Data, is_single<>>)
221  auto operator()(Data d, DSF sf) const {
223  }
224  PUSHMI_TEMPLATE(class Data, class DSF, class DEXF)
225  (requires Sender<Data, is_single<>>&& Invocable<DEXF&, Data&>)
226  auto operator()(Data d, DSF sf, DEXF exf) const {
228  std::move(d), std::move(sf), std::move(exf)};
229  }
230 } const make_single_sender{};
231 
233 // deduction guides
234 #if __cpp_deduction_guides >= 201703
236 
237 PUSHMI_TEMPLATE(class SF)
238  (requires True<> PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
240 
241 PUSHMI_TEMPLATE(class SF, class EXF)
242  (requires True<> && Invocable<EXF&>
243  PUSHMI_BROKEN_SUBSUMPTION(&& not Sender<SF>))
245 
246 PUSHMI_TEMPLATE(class Data)
247  (requires True<> && Sender<Data, is_single<>>)
249 
250 PUSHMI_TEMPLATE(class Data, class DSF)
251  (requires Sender<Data, is_single<>>)
253 
254 PUSHMI_TEMPLATE(class Data, class DSF, class DEXF)
255  (requires Sender<Data, is_single<>> && Invocable<DEXF&, Data&>)
257 #endif
258 
259 template<>
261 
262 } // namespace pushmi
263 } // namespace folly
static void s_op(data &, data *)
Definition: single_sender.h:37
constexpr single_sender(Data data, DSF sf, DEXF exf)
std::true_type True
Definition: TypeList.h:82
any_executor< E >(* executor_)(data &)
Definition: single_sender.h:43
char buffer_[sizeof(std::tuple< VN... >)]
Definition: single_sender.h:29
static constexpr vtable const noop_
Definition: single_sender.h:46
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
STL namespace.
—— Concurrent Priority Queue Implementation ——
Definition: AtomicBitSet.h:29
static constexpr bool insitu()
Definition: single_sender.h:32
requires E e noexcept(noexcept(s.error(std::move(e))))
requires PUSHMI_EXP(lazy::Receiver< Out > PUSHMI_AND lazy::Invocable< SF &, Out >)) void submit(Out out)
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
requires PUSHMI_EXP(lazy::Receiver< Out > PUSHMI_AND lazy::Invocable< DSF &, Data &, Out >)) void submit(Out out)
static void s_submit(data &, any_receiver< E, VN... >)
Definition: single_sender.h:41
#define PUSHMI_AND
Definition: concept_def.h:424
std::enable_if_t<!std::is_same< U, any_single_sender >::value, U > wrapped_t
Definition: single_sender.h:94
any_single_sender(Wrapped obj, std::false_type)
Definition: single_sender.h:49
constexpr auto data(C &c) -> decltype(c.data())
Definition: Access.h:71
constexpr single_sender(SF sf, EXF exf)
static const char *const value
Definition: Conv.cpp:50
#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
void(* submit_)(data &, any_receiver< E, VN... >)
Definition: single_sender.h:44
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
requires SenderTo< wrapped_t< Wrapped >, any_receiver< E, VN... > > any_single_sender(Wrapped obj) noexcept(insitu< Wrapped >())
static set< string > s
const
Definition: upload.py:398
bool_constant< false > false_type
Definition: gtest-port.h:2209
#define PUSHMI_TYPE_CONSTRAINT(...)
Definition: concept_def.h:420
union folly::pushmi::any_single_sender::data data_
constexpr single_sender(Data data, DSF sf)
void swap(SwapTrackingAlloc< T > &, SwapTrackingAlloc< T > &)
Definition: F14TestUtil.h:414
void submit(any_receiver< E, VN... > out)
#define PUSHMI_BROKEN_SUBSUMPTION(...)
Definition: concept_def.h:419
property_set_insert_t< properties_t< Data >, property_set< is_sender<>, is_single<>>> properties
any_single_sender(any_single_sender &&that) noexcept
any_single_sender(Wrapped obj, std::true_type) noexcept
Definition: single_sender.h:70
any_single_sender & operator=(any_single_sender &&that) noexcept
PUSHMI_INLINE_VAR constexpr struct folly::pushmi::make_single_sender_fn make_single_sender
static any_executor< E > s_executor(data &)
Definition: single_sender.h:38