CMS 3D CMS Logo

chain_first.h
Go to the documentation of this file.
1 #ifndef FWCore_Concurrency_chain_first_h
2 #define FWCore_Concurrency_chain_first_h
3 // -*- C++ -*-
4 //
5 // Package: Concurrency
6 // function : edm::waiting_task::chain::first
7 //
17 //
18 // Original Author: Chris Jones
19 // Created: Thu Feb 21 13:46:31 CST 2013
20 // $Id$
21 //
22 
23 // system include files
24 #include <atomic>
25 #include <exception>
26 #include <memory>
27 #include <type_traits>
28 
29 // user include files
32 
33 // forward declarations
34 
35 namespace edm {
36  namespace waiting_task::detail {
37 
38  template <class, class = void>
39  struct has_exception_handling : std::false_type {};
40 
41  template <class T>
43  std::void_t<decltype(std::declval<T&>()(
44  static_cast<std::exception_ptr const*>(nullptr), edm::WaitingTaskHolder()))>>
45  : std::true_type {};
46 
47  template <typename F>
49  AutoExceptionHandler(F&& iF) : f_{std::forward<F>(iF)} {}
50 
51  void operator()(std::exception_ptr const* iPtr, edm::WaitingTaskHolder h) noexcept {
52  if (iPtr) {
53  h.doneWaiting(*iPtr);
54  } else {
55  CMS_SA_ALLOW try { f_(h); } catch (...) {
56  h.doneWaiting(std::current_exception());
57  }
58  }
59  }
60 
61  private:
62  F f_;
63  };
64 
65  template <typename E, typename F>
67  ExplicitExceptionHandler(E&& iE, F&& iF) : except_(std::forward<E>(iE)), f_{std::forward<F>(iF)} {}
68 
69  void operator()(std::exception_ptr const* iPtr, edm::WaitingTaskHolder h) noexcept {
70  if (iPtr) {
71  except_(*iPtr);
72  h.doneWaiting(*iPtr);
73  } else {
74  CMS_SA_ALLOW try { f_(h); } catch (...) {
75  h.doneWaiting(std::current_exception());
76  }
77  }
78  }
79 
80  private:
82  F f_;
83  };
84 
88  template <typename E>
90  constexpr IfExceptionAdapter(E&& iE) : except_(std::forward<E>(iE)) {}
91 
92  template <typename F>
93  constexpr auto else_(F&& iF) {
94  return ExplicitExceptionHandler<E, F>(std::move(except_), std::forward<F>(iF));
95  }
96 
97  private:
99  };
100 
101  template <typename... T>
103 
104  template <typename F>
105  struct Conditional {};
106 
107  template <typename F>
109  constexpr explicit ConditionalAdaptor(bool iCond, F&& iF) : f_(std::forward<F>(iF)), condition_(iCond) {}
110 
111  template <typename... T>
112  [[nodiscard]] constexpr auto pipe(WaitingTaskChain<T...> iChain) {
114  }
115 
116  F f_;
118  };
119 
120  template <typename F>
121  struct ThenAdaptor {
122  constexpr explicit ThenAdaptor(F&& iF) : f_(std::forward<F>(iF)) {}
123 
124  template <typename... T>
125  [[nodiscard]] constexpr auto pipe(WaitingTaskChain<T...> iChain) {
126  return WaitingTaskChain<F, T...>(std::move(f_), std::move(iChain));
127  }
128 
129  private:
130  F f_;
131  };
132 
133  struct RunLastAdaptor {
135 
136  template <typename... T>
137  constexpr void pipe(WaitingTaskChain<T...>&& iChain) {
138  iChain.runLast(std::move(task_));
139  }
140 
141  private:
143  };
144 
147 
148  template <typename... T>
149  constexpr auto pipe(WaitingTaskChain<T...>&& iChain) {
150  return iChain.lastTask(std::move(task_));
151  }
152 
153  private:
155  };
156 
157  template <typename U>
158  struct WaitingTaskChain<U> {
159  constexpr explicit WaitingTaskChain(U&& iU) : f_{std::forward<U>(iU)} {}
160 
162  return WaitingTaskHolder(
163  *iV.group(),
164  make_waiting_task([f = std::move(f_), v = std::move(iV)](const std::exception_ptr* iPtr) mutable {
165  f(iPtr, std::move(v));
166  }));
167  }
168 
169  void runLast(WaitingTaskHolder iH) { f_(nullptr, std::move(iH)); }
170 
171  template <typename V>
172  friend auto operator|(WaitingTaskChain<U> iChain, V&& iV) {
173  return iV.pipe(std::move(iChain));
174  }
175 
176  private:
177  U f_;
178  };
179 
180  template <typename U, typename... T>
181  struct WaitingTaskChain<U, T...> {
182  explicit constexpr WaitingTaskChain(U&& iU, WaitingTaskChain<T...> iL)
183  : l_(std::move(iL)), f_{std::forward<U>(iU)} {}
184 
186  return l_.lastTask(WaitingTaskHolder(
187  *iV.group(),
188  make_waiting_task([f = std::move(f_), v = std::move(iV)](std::exception_ptr const* iPtr) mutable {
189  f(iPtr, std::move(v));
190  })));
191  }
192 
194  l_.runLast(WaitingTaskHolder(
195  *iV.group(),
196  make_waiting_task([f = std::move(f_), v = std::move(iV)](std::exception_ptr const* iPtr) mutable {
197  f(iPtr, std::move(v));
198  })));
199  }
200 
201  template <typename V>
202  friend auto operator|(WaitingTaskChain<U, T...> iChain, V&& iV) {
203  return iV.pipe(std::move(iChain));
204  }
205 
206  private:
208  U f_;
209  };
210 
211  template <typename U, typename... T>
213  explicit constexpr WaitingTaskChain(bool iCondition, U&& iU, WaitingTaskChain<T...> iL)
214  : l_(std::move(iL)), f_{std::forward<U>(iU)}, condition_(iCondition) {}
215 
217  : l_(std::move(iL)), f_{std::move<U>(iC.f_)}, condition_(iC.condition_) {}
218 
220  if (condition_) {
221  return l_.lastTask(WaitingTaskHolder(
222  *iV.group(),
223  make_waiting_task([f = std::move(f_), v = std::move(iV)](std::exception_ptr const* iPtr) mutable {
224  f(iPtr, std::move(v));
225  })));
226  }
227  return l_.lastTask(iV);
228  }
229 
231  if (condition_) {
232  l_.runLast(WaitingTaskHolder(
233  *iV.group(),
234  make_waiting_task([f = std::move(f_), v = std::move(iV)](std::exception_ptr const* iPtr) mutable {
235  f(iPtr, std::move(v));
236  })));
237  } else {
238  l_.runLast(iV);
239  }
240  }
241 
242  template <typename V>
243  friend auto operator|(WaitingTaskChain<Conditional<U>, T...> iChain, V&& iV) {
244  return iV.pipe(std::move(iChain));
245  }
246 
247  private:
249  U f_;
251  };
252 
253  } // namespace waiting_task::detail
254  namespace waiting_task::chain {
255 
259  template <typename F>
260  [[nodiscard]] constexpr auto first(F&& iF) {
261  using namespace detail;
262  if constexpr (has_exception_handling<F>::value) {
263  return WaitingTaskChain<F>(std::forward<F>(iF));
264  } else {
265  return WaitingTaskChain<AutoExceptionHandler<F>>(AutoExceptionHandler<F>(std::forward<F>(iF)));
266  }
267  }
268 
276  template <typename O>
277  [[nodiscard]] constexpr auto then(O&& iO) {
278  using namespace detail;
279  if constexpr (has_exception_handling<O>::value) {
280  return ThenAdaptor<O>(std::forward<O>(iO));
281  } else {
282  return ThenAdaptor<AutoExceptionHandler<O>>(AutoExceptionHandler<O>(std::forward<O>(iO)));
283  }
284  }
285 
287  template <typename O>
288  [[nodiscard]] constexpr auto ifThen(bool iValue, O&& iO) {
289  using namespace detail;
290  if constexpr (has_exception_handling<O>::value) {
291  return ConditionalAdaptor<O>(iValue, std::forward<O>(iO));
292  } else {
293  return ConditionalAdaptor<AutoExceptionHandler<O>>(iValue, AutoExceptionHandler<O>(std::forward<O>(iO)));
294  }
295  }
296 
297  [[nodiscard]] inline auto runLast(edm::WaitingTaskHolder iTask) { return detail::RunLastAdaptor(std::move(iTask)); }
298 
299  [[nodiscard]] inline auto lastTask(edm::WaitingTaskHolder iTask) {
300  return detail::LastTaskAdaptor(std::move(iTask));
301  }
302 
306  template <typename E>
307  [[nodiscard]] constexpr auto ifException(E&& iE) {
308  return detail::IfExceptionAdapter(std::forward<E>(iE));
309  }
310 
311  } // namespace waiting_task::chain
312 } // namespace edm
313 
314 #endif
WaitingTaskHolder lastTask(WaitingTaskHolder iV)
Definition: chain_first.h:161
#define CMS_SA_ALLOW
constexpr WaitingTaskChain(U &&iU, WaitingTaskChain< T... > iL)
Definition: chain_first.h:182
constexpr auto first(F &&iF)
Definition: chain_first.h:260
constexpr auto then(O &&iO)
Definition: chain_first.h:277
oneapi::tbb::task_group * group() const noexcept
friend auto operator|(WaitingTaskChain< U, T... > iChain, V &&iV)
Definition: chain_first.h:202
uint32_t T const *__restrict__ uint32_t const *__restrict__ int32_t int Histo::index_type cudaStream_t V
auto runLast(edm::WaitingTaskHolder iTask)
Definition: chain_first.h:297
constexpr auto pipe(WaitingTaskChain< T... > &&iChain)
Definition: chain_first.h:149
constexpr void pipe(WaitingTaskChain< T... > &&iChain)
Definition: chain_first.h:137
FunctorWaitingTask< F > * make_waiting_task(F f)
Definition: WaitingTask.h:101
double f[11][100]
constexpr WaitingTaskChain(Conditional< U > iC, WaitingTaskChain< T... > iL)
Definition: chain_first.h:216
constexpr auto ifThen(bool iValue, O &&iO)
Only runs this task if the condition (which is known at the call time) is true. If false...
Definition: chain_first.h:288
friend auto operator|(WaitingTaskChain< Conditional< U >, T... > iChain, V &&iV)
Definition: chain_first.h:243
WaitingTaskHolder lastTask(WaitingTaskHolder iV)
Definition: chain_first.h:185
void operator()(std::exception_ptr const *iPtr, edm::WaitingTaskHolder h) noexcept
Definition: chain_first.h:69
constexpr auto ifException(E &&iE)
Definition: chain_first.h:307
constexpr WaitingTaskChain(bool iCondition, U &&iU, WaitingTaskChain< T... > iL)
Definition: chain_first.h:213
constexpr auto pipe(WaitingTaskChain< T... > iChain)
Definition: chain_first.h:125
HLT enums.
friend auto operator|(WaitingTaskChain< U > iChain, V &&iV)
Definition: chain_first.h:172
constexpr ConditionalAdaptor(bool iCond, F &&iF)
Definition: chain_first.h:109
auto lastTask(edm::WaitingTaskHolder iTask)
Definition: chain_first.h:299
void operator()(std::exception_ptr const *iPtr, edm::WaitingTaskHolder h) noexcept
Definition: chain_first.h:51
RunLastAdaptor(edm::WaitingTaskHolder iT)
Definition: chain_first.h:134
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:163
The Signals That Services Can Subscribe To This is based on ActivityRegistry h
Helper function to determine trigger accepts.
Definition: Activities.doc:4
long double T
def move(src, dest)
Definition: eostools.py:511
LastTaskAdaptor(edm::WaitingTaskHolder iT)
Definition: chain_first.h:146
constexpr auto pipe(WaitingTaskChain< T... > iChain)
Definition: chain_first.h:112