CMS 3D CMS Logo

Callback.h
Go to the documentation of this file.
1 #ifndef FWCore_Framework_Callback_h
2 #define FWCore_Framework_Callback_h
3 // -*- C++ -*-
4 //
5 // Package: Framework
6 // Class : Callback
7 //
16 //
17 // Author: Chris Jones
18 // Created: Sun Apr 17 14:30:24 EDT 2005
19 //
20 
21 // system include files
22 #include <array>
23 #include <vector>
24 #include <type_traits>
25 #include <atomic>
26 // user include files
38 
39 namespace edm {
40  void exceptionContext(cms::Exception&, ESModuleCallingContext const&);
41 
42  namespace eventsetup {
43  class EventSetupRecordImpl;
44 
45  // The default decorator that does nothing
46  template <typename TRecord>
48  void pre(const TRecord&) {}
49  void post(const TRecord&) {}
50  };
51 
52  template <typename T, //producer's type
53  typename TFunc, //functor type
54  typename TReturn, //return type of the producer's method
55  typename TRecord, //the record passed in as an argument
56  typename TDecorator //allows customization using pre/post calls
57  = CallbackSimpleDecorator<TRecord>>
58  class Callback {
59  public:
60  Callback(T* iProd, TFunc iFunc, unsigned int iID, const TDecorator& iDec = TDecorator())
61  : Callback(iProd, std::make_shared<TFunc>(std::move(iFunc)), iID, iDec) {}
62 
63  Callback(T* iProd, std::shared_ptr<TFunc> iFunc, unsigned int iID, const TDecorator& iDec = TDecorator())
64  : proxyData_{},
65  producer_(iProd),
66  callingContext_(&iProd->description()),
67  function_(std::move(iFunc)),
68  id_(iID),
70  decorator_(iDec) {}
71 
73 
74  Callback(const Callback&) = delete;
75  const Callback& operator=(const Callback&) = delete;
76 
78  EventSetupRecordImpl const* iRecord,
79  EventSetupImpl const* iEventSetupImpl,
80  ServiceToken const& token,
81  ESParentContext const& iParent) {
82  bool expected = false;
83  auto doPrefetch = wasCalledForThisRecord_.compare_exchange_strong(expected, true);
84  taskList_.add(iTask);
85  auto group = iTask.group();
86  if (doPrefetch) {
89  if UNLIKELY (producer_->hasMayConsumes()) {
90  //after prefetching need to do the mayGet
91  ServiceWeakToken weakToken = token;
92  auto mayGetTask = edm::make_waiting_task(
93  [this, iRecord, iEventSetupImpl, weakToken, group](std::exception_ptr const* iExcept) {
94  if (iExcept) {
95  runProducerAsync(group, iExcept, iRecord, iEventSetupImpl, weakToken.lock());
96  return;
97  }
98  if (handleMayGet(iRecord, iEventSetupImpl)) {
99  auto runTask = edm::make_waiting_task(
100  [this, group, iRecord, iEventSetupImpl, weakToken](std::exception_ptr const* iExcept) {
101  runProducerAsync(group, iExcept, iRecord, iEventSetupImpl, weakToken.lock());
102  });
104  iEventSetupImpl,
105  &((*postMayGetProxies_).front()),
106  weakToken.lock());
107  } else {
108  runProducerAsync(group, iExcept, iRecord, iEventSetupImpl, weakToken.lock());
109  }
110  });
111 
112  //Get everything we can before knowing about the mayGets
113  prefetchNeededDataAsync(WaitingTaskHolder(*group, mayGetTask), iEventSetupImpl, getTokenIndices(), token);
114  } else {
115  ServiceWeakToken weakToken = token;
117  [this, group, iRecord, iEventSetupImpl, weakToken](std::exception_ptr const* iExcept) {
118  runProducerAsync(group, iExcept, iRecord, iEventSetupImpl, weakToken.lock());
119  });
121  }
122  }
123  }
124 
125  template <class DataT>
126  void holdOntoPointer(DataT* iData) {
128  }
129 
130  void storeReturnedValues(TReturn iReturn) {
132  setData<typename type::head_type, typename type::tail_type>(iReturn);
133  }
134 
135  template <class RemainingContainerT, class DataT, class ProductsT>
136  void setData(ProductsT& iProducts) {
137  DataT* temp = reinterpret_cast<DataT*>(proxyData_[produce::find_index<TReturn, DataT>::value]);
138  if (nullptr != temp) {
139  moveFromTo(iProducts, *temp);
140  }
141  if constexpr (not std::is_same_v<produce::Null, RemainingContainerT>) {
142  setData<typename RemainingContainerT::head_type, typename RemainingContainerT::tail_type>(iProducts);
143  }
144  }
146  wasCalledForThisRecord_ = false;
147  taskList_.reset();
148  }
149 
150  unsigned int transitionID() const { return id_; }
151  ESProxyIndex const* getTokenIndices() const { return producer_->getTokenIndices(id_); }
152 
153  private:
155  EventSetupImpl const* iImpl,
156  ESProxyIndex const* proxies,
157  edm::ServiceToken const& token) const {
158  auto recs = producer_->getTokenRecordIndices(id_);
159  auto n = producer_->numberOfTokenIndices(id_);
160  for (size_t i = 0; i != n; ++i) {
161  auto rec = iImpl->findImpl(recs[i]);
162  if (rec) {
163  rec->prefetchAsync(task, proxies[i], iImpl, token, edm::ESParentContext{&callingContext_});
164  }
165  }
166  }
167 
168  bool handleMayGet(EventSetupRecordImpl const* iRecord, EventSetupImpl const* iEventSetupImpl) {
169  //Handle mayGets
170  TRecord rec;
172  rec.setImpl(iRecord, transitionID(), getTokenIndices(), iEventSetupImpl, &pc);
173  postMayGetProxies_ = producer_->updateFromMayConsumes(id_, rec);
174  return static_cast<bool>(postMayGetProxies_);
175  }
176 
177  void runProducerAsync(oneapi::tbb::task_group* iGroup,
178  std::exception_ptr const* iExcept,
179  EventSetupRecordImpl const* iRecord,
180  EventSetupImpl const* iEventSetupImpl,
181  ServiceToken const& token) {
182  if (iExcept) {
183  //The cache held by the CallbackProxy was already set to invalid at the beginning of the IOV
184  taskList_.doneWaiting(*iExcept);
185  return;
186  }
188  ServiceWeakToken weakToken = token;
189  producer_->queue().push(*iGroup, [this, iRecord, iEventSetupImpl, weakToken]() {
191  std::exception_ptr exceptPtr;
192  try {
193  convertException::wrap([this, iRecord, iEventSetupImpl, weakToken] {
194  auto proxies = getTokenIndices();
195  if (postMayGetProxies_) {
196  proxies = &((*postMayGetProxies_).front());
197  }
198  TRecord rec;
200  rec.setImpl(iRecord, transitionID(), proxies, iEventSetupImpl, &pc);
201  ServiceRegistry::Operate operate(weakToken.lock());
203  struct EndGuard {
204  EndGuard(EventSetupRecordImpl const* iRecord, ESModuleCallingContext const& iContext)
205  : record_{iRecord}, context_{iContext} {}
206  ~EndGuard() { record_->activityRegistry()->postESModuleSignal_.emit(record_->key(), context_); }
207  EventSetupRecordImpl const* record_;
208  ESModuleCallingContext const& context_;
209  };
210  EndGuard guard(iRecord, callingContext_);
211  decorator_.pre(rec);
213  decorator_.post(rec);
214  });
215  } catch (cms::Exception& iException) {
217  exceptPtr = std::current_exception();
218  }
219  taskList_.doneWaiting(exceptPtr);
220  });
221  }
222 
224  std::optional<std::vector<ESProxyIndex>> postMayGetProxies_;
228  // Using std::shared_ptr in order to share the state of the
229  // functor across all clones
230  std::shared_ptr<TFunc> function_;
231  // This transition id identifies which setWhatProduced call this Callback is associated with
232  const unsigned int id_;
233  std::atomic<bool> wasCalledForThisRecord_;
234  TDecorator decorator_;
235  };
236  } // namespace eventsetup
237 } // namespace edm
238 
239 #endif
const Callback & operator=(const Callback &)=delete
std::optional< std::vector< ESProxyIndex > > postMayGetProxies_
Definition: Callback.h:224
void exceptionContext(cms::Exception &, ESModuleCallingContext const &)
void prefetchAsync(WaitingTaskHolder iTask, ESProxyIndex iProxyIndex, EventSetupImpl const *, ServiceToken const &, ESParentContext) const
prefetch the data to setup for subsequent calls to getImplementation
void prefetchNeededDataAsync(WaitingTaskHolder task, EventSetupImpl const *iImpl, ESProxyIndex const *proxies, edm::ServiceToken const &token) const
Definition: Callback.h:154
PreESModulePrefetching preESModulePrefetchingSignal_
std::shared_ptr< TFunc > function_
Definition: Callback.h:230
void reset()
Resets access to the resource so that added tasks will wait.
void runProducerAsync(oneapi::tbb::task_group *iGroup, std::exception_ptr const *iExcept, EventSetupRecordImpl const *iRecord, EventSetupImpl const *iEventSetupImpl, ServiceToken const &token)
Definition: Callback.h:177
PostESModulePrefetching postESModulePrefetchingSignal_
std::atomic< bool > wasCalledForThisRecord_
Definition: Callback.h:233
constexpr element_type const * get() const
oneapi::tbb::task_group * group() const noexcept
void emit(Args &&... args) const
Definition: Signal.h:48
void doneWaiting(std::exception_ptr iPtr)
Signals that the resource is now available and tasks should be spawned.
void holdOntoPointer(DataT *iData)
Definition: Callback.h:126
ESModuleCallingContext callingContext_
Definition: Callback.h:226
void moveFromTo(FromT &iFrom, ToT &iTo)
void add(oneapi::tbb::task_group *, WaitingTask *)
Adds task to the waiting list.
FunctorWaitingTask< F > * make_waiting_task(F f)
Definition: WaitingTask.h:92
void setData(ProductsT &iProducts)
Definition: Callback.h:136
unsigned int transitionID() const
Definition: Callback.h:150
ServiceToken lock() const
Definition: ServiceToken.h:101
void prefetchAsync(WaitingTaskHolder iTask, EventSetupRecordImpl const *iRecord, EventSetupImpl const *iEventSetupImpl, ServiceToken const &token, ESParentContext const &iParent)
Definition: Callback.h:77
EventSetupRecordKey const & key() const
edm::propagate_const< T * > producer_
Definition: Callback.h:225
edm::WaitingTaskList taskList_
Definition: Callback.h:227
PreESModule preESModuleSignal_
void setContext(State state, ESParentContext const &parent)
std::array< void *, produce::size< TReturn >::value > proxyData_
Definition: Callback.h:223
Callback * clone()
Definition: Callback.h:72
HLT enums.
const unsigned int id_
Definition: Callback.h:232
bool handleMayGet(EventSetupRecordImpl const *iRecord, EventSetupImpl const *iEventSetupImpl)
Definition: Callback.h:168
auto wrap(F iFunc) -> decltype(iFunc())
#define UNLIKELY(x)
Definition: Likely.h:21
Callback(T *iProd, TFunc iFunc, unsigned int iID, const TDecorator &iDec=TDecorator())
Definition: Callback.h:60
long double T
Callback(T *iProd, std::shared_ptr< TFunc > iFunc, unsigned int iID, const TDecorator &iDec=TDecorator())
Definition: Callback.h:63
eventsetup::EventSetupRecordImpl const * findImpl(const eventsetup::EventSetupRecordKey &) const
void storeReturnedValues(TReturn iReturn)
Definition: Callback.h:130
def move(src, dest)
Definition: eostools.py:511
ActivityRegistry const * activityRegistry() const noexcept
ESProxyIndex const * getTokenIndices() const
Definition: Callback.h:151