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
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::operator|
friend auto operator|(WaitingTaskChain< Conditional< U >, T... > iChain, V &&iV)
Definition: chain_first.h:243
edm::waiting_task::detail::IfExceptionAdapter
Definition: chain_first.h:89
edm::waiting_task::detail::RunLastAdaptor::task_
edm::WaitingTaskHolder task_
Definition: chain_first.h:142
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::lastTask
WaitingTaskHolder lastTask(WaitingTaskHolder iV)
Definition: chain_first.h:219
edm::waiting_task::detail::AutoExceptionHandler
Definition: chain_first.h:48
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::l_
WaitingTaskChain< T... > l_
Definition: chain_first.h:248
f
double f[11][100]
Definition: MuScleFitUtils.cc:78
edm::waiting_task::detail::AutoExceptionHandler::f_
F f_
Definition: chain_first.h:62
WaitingTaskHolder.h
edm::waiting_task::detail::WaitingTaskChain< U, T... >::l_
WaitingTaskChain< T... > l_
Definition: chain_first.h:207
edm::waiting_task::detail::WaitingTaskChain< U, T... >::WaitingTaskChain
constexpr WaitingTaskChain(U &&iU, WaitingTaskChain< T... > iL)
Definition: chain_first.h:182
edm
HLT enums.
Definition: AlignableModifier.h:19
edm::waiting_task::chain::first
constexpr auto first(F &&iF)
Definition: chain_first.h:260
edm::waiting_task::detail::WaitingTaskChain< U, T... >::f_
U f_
Definition: chain_first.h:208
edm::waiting_task::detail::ThenAdaptor::ThenAdaptor
constexpr ThenAdaptor(F &&iF)
Definition: chain_first.h:122
edm::waiting_task::detail::ThenAdaptor::f_
F f_
Definition: chain_first.h:130
edm::waiting_task::detail::WaitingTaskChain< U >::operator|
friend auto operator|(WaitingTaskChain< U > iChain, V &&iV)
Definition: chain_first.h:172
detail
Definition: ConvertingESProducerWithDependenciesT.h:23
findQualityFiles.v
v
Definition: findQualityFiles.py:179
edm::waiting_task::detail::WaitingTaskChain< U >::lastTask
WaitingTaskHolder lastTask(WaitingTaskHolder iV)
Definition: chain_first.h:161
edm::waiting_task::detail::LastTaskAdaptor::pipe
constexpr auto pipe(WaitingTaskChain< T... > &&iChain)
Definition: chain_first.h:149
CMS_SA_ALLOW
#define CMS_SA_ALLOW
Definition: thread_safety_macros.h:5
edm::waiting_task::detail::ExplicitExceptionHandler::ExplicitExceptionHandler
ExplicitExceptionHandler(E &&iE, F &&iF)
Definition: chain_first.h:67
edm::waiting_task::detail::ConditionalAdaptor
Definition: chain_first.h:108
edm::waiting_task::chain::runLast
auto runLast(edm::WaitingTaskHolder iTask)
Definition: chain_first.h:297
F
static uInt32 F(BLOWFISH_CTX *ctx, uInt32 x)
Definition: blowfish.cc:163
edm::waiting_task::detail::has_exception_handling
Definition: chain_first.h:39
edm::waiting_task::detail::Conditional
Definition: chain_first.h:105
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::runLast
void runLast(WaitingTaskHolder iV)
Definition: chain_first.h:230
edm::waiting_task::chain::then
constexpr auto then(O &&iO)
Definition: chain_first.h:277
edm::waiting_task::detail::ConditionalAdaptor::ConditionalAdaptor
constexpr ConditionalAdaptor(bool iCond, F &&iF)
Definition: chain_first.h:109
edm::waiting_task::detail::ThenAdaptor
Definition: chain_first.h:121
edm::waiting_task::detail::RunLastAdaptor::RunLastAdaptor
RunLastAdaptor(edm::WaitingTaskHolder iT)
Definition: chain_first.h:134
edm::waiting_task::detail::WaitingTaskChain< U, T... >::operator|
friend auto operator|(WaitingTaskChain< U, T... > iChain, V &&iV)
Definition: chain_first.h:202
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::condition_
bool condition_
Definition: chain_first.h:250
edm::waiting_task::detail::LastTaskAdaptor::task_
edm::WaitingTaskHolder task_
Definition: chain_first.h:154
edm::waiting_task::detail::AutoExceptionHandler::AutoExceptionHandler
AutoExceptionHandler(F &&iF)
Definition: chain_first.h:49
h
edm::waiting_task::detail::WaitingTaskChain< U, T... >
Definition: chain_first.h:181
mitigatedMETSequence_cff.U
U
Definition: mitigatedMETSequence_cff.py:36
edm::waiting_task::detail::WaitingTaskChain< U >::WaitingTaskChain
constexpr WaitingTaskChain(U &&iU)
Definition: chain_first.h:159
edm::waiting_task::detail::ExplicitExceptionHandler::except_
E except_
Definition: chain_first.h:81
edm::waiting_task::detail::IfExceptionAdapter::except_
E except_
Definition: chain_first.h:98
edm::waiting_task::chain::lastTask
auto lastTask(edm::WaitingTaskHolder iTask)
Definition: chain_first.h:299
edm::make_waiting_task
FunctorWaitingTask< F > * make_waiting_task(F f)
Definition: WaitingTask.h:101
edm::WaitingTaskHolder
Definition: WaitingTaskHolder.h:32
edm::waiting_task::detail::ExplicitExceptionHandler::operator()
void operator()(std::exception_ptr const *iPtr, edm::WaitingTaskHolder h) noexcept
Definition: chain_first.h:69
cms::cuda::V
uint32_t const T *__restrict__ const uint32_t *__restrict__ int32_t int Histo::index_type cudaStream_t V
Definition: HistoContainer.h:51
thread_safety_macros.h
edm::waiting_task::detail::WaitingTaskChain< U, T... >::runLast
void runLast(WaitingTaskHolder iV)
Definition: chain_first.h:193
edm::waiting_task::detail::WaitingTaskChain< U, T... >::lastTask
WaitingTaskHolder lastTask(WaitingTaskHolder iV)
Definition: chain_first.h:185
edm::waiting_task::detail::RunLastAdaptor
Definition: chain_first.h:133
edm::waiting_task::detail::ThenAdaptor::pipe
constexpr auto pipe(WaitingTaskChain< T... > iChain)
Definition: chain_first.h:125
edm::waiting_task::detail::IfExceptionAdapter::IfExceptionAdapter
constexpr IfExceptionAdapter(E &&iE)
Definition: chain_first.h:90
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::WaitingTaskChain
constexpr WaitingTaskChain(bool iCondition, U &&iU, WaitingTaskChain< T... > iL)
Definition: chain_first.h:213
edm::waiting_task::detail::AutoExceptionHandler::operator()
void operator()(std::exception_ptr const *iPtr, edm::WaitingTaskHolder h) noexcept
Definition: chain_first.h:51
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::WaitingTaskChain
constexpr WaitingTaskChain(Conditional< U > iC, WaitingTaskChain< T... > iL)
Definition: chain_first.h:216
edm::waiting_task::detail::WaitingTaskChain< U >::f_
U f_
Definition: chain_first.h:177
eostools.move
def move(src, dest)
Definition: eostools.py:511
std
Definition: JetResolutionObject.h:76
T
long double T
Definition: Basic3DVectorLD.h:48
relativeConstraints.value
value
Definition: relativeConstraints.py:53
edm::waiting_task::detail::WaitingTaskChain< Conditional< U >, T... >::f_
U f_
Definition: chain_first.h:249
edm::waiting_task::detail::RunLastAdaptor::pipe
constexpr void pipe(WaitingTaskChain< T... > &&iChain)
Definition: chain_first.h:137
edm::waiting_task::chain::ifThen
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
edm::waiting_task::detail::ExplicitExceptionHandler::f_
F f_
Definition: chain_first.h:82
edm::waiting_task::detail::LastTaskAdaptor::LastTaskAdaptor
LastTaskAdaptor(edm::WaitingTaskHolder iT)
Definition: chain_first.h:146
edm::waiting_task::detail::ConditionalAdaptor::condition_
bool condition_
Definition: chain_first.h:117
edm::waiting_task::detail::WaitingTaskChain
Definition: chain_first.h:102
edm::waiting_task::detail::WaitingTaskChain< U >
Definition: chain_first.h:158
edm::waiting_task::detail::ConditionalAdaptor::pipe
constexpr auto pipe(WaitingTaskChain< T... > iChain)
Definition: chain_first.h:112
edm::waiting_task::detail::ExplicitExceptionHandler
Definition: chain_first.h:66
edm::waiting_task::detail::IfExceptionAdapter::else_
constexpr auto else_(F &&iF)
Definition: chain_first.h:93
edm::waiting_task::detail::WaitingTaskChain< U >::runLast
void runLast(WaitingTaskHolder iH)
Definition: chain_first.h:169
edm::waiting_task::detail::ConditionalAdaptor::f_
F f_
Definition: chain_first.h:116
edm::WaitingTaskHolder::group
tbb::task_group * group() const noexcept
Definition: WaitingTaskHolder.h:77
edm::waiting_task::detail::LastTaskAdaptor
Definition: chain_first.h:145
edm::waiting_task::chain::ifException
constexpr auto ifException(E &&iE)
Definition: chain_first.h:307