2 * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
5 * @file StoreGate/WriteDecorHandle.icc
6 * @author scott snyder <snyder@bnl.gov>
8 * @brief Handle class for adding a decoration to an object.
12 #include "CxxUtils/checker_macros.h"
13 #include "StoreGate/exceptions.h"
20 * @brief Constructor from a WriteDecorHandleKey.
21 * @param key The key object holding the clid/key/store/attr.
23 * This will raise an exception if the StoreGate key is blank,
24 * or if the event store cannot be found.
26 template <class T, class D>
27 WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key)
28 : Base (key.contHandleKey(), nullptr),
29 m_decorKey (key.key()),
30 m_acc (SG::decorKeyFromKey (key.key())),
31 m_renounced (key.renounced()),
38 * @brief Constructor from a ReadDecorHandleKey and an explicit event context.
39 * @param key The key object holding the clid/key.
40 * @param ctx The event context.
42 * This will raise an exception if the StoreGate key is blank,
43 * or if the event store cannot be found.
45 * If the default event store has been requested, then the thread-specific
46 * store from the event context will be used.
48 template <class T, class D>
49 WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandleKey<T>& key,
50 const EventContext& ctx)
51 : Base (key.contHandleKey(), &ctx),
52 m_decorKey (key.key()),
53 m_acc (SG::decorKeyFromKey (key.key())),
54 m_renounced (key.renounced()),
61 * @brief Copy constructor.
63 template <class T, class D>
64 WriteDecorHandle<T, D>::WriteDecorHandle (const WriteDecorHandle& rhs)
66 m_decorKey (rhs.m_decorKey),
68 m_renounced (rhs.m_renounced),
69 m_decorated (rhs.m_decorated)
75 * @brief Move constructor.
77 template <class T, class D>
78 WriteDecorHandle<T, D>::WriteDecorHandle (WriteDecorHandle&& rhs)
79 : Base (std::move (rhs)),
80 m_decorKey (std::move (rhs.m_decorKey)),
81 m_acc (std::move (rhs.m_acc)),
82 m_renounced (rhs.m_renounced),
83 m_decorated (rhs.m_decorated)
85 rhs.m_decorated = false;
90 * @brief Destructor. This will lock the decoration.
92 template <class T, class D>
93 WriteDecorHandle<T, D>::~WriteDecorHandle()
95 // Lock the decoration. But don't do anything if we haven't touched it.
97 const IConstAuxStore* store = this->vectorData()->getConstStore();
99 // Lock the decoration and clear its entry in the cache.
100 // Casting away const should be ok because no other thread should
101 // be looking at this decoration yet.
102 auto avd_nc ATLAS_THREAD_SAFE = const_cast<SG::AuxVectorData*> (this->vectorData());
103 avd_nc->lockDecoration (auxid());
110 * @brief Assignment operator.
112 template <class T, class D>
113 WriteDecorHandle<T, D>& WriteDecorHandle<T, D>::operator= (const WriteDecorHandle& rhs)
116 *static_cast<Base*>(this) = rhs;
118 m_decorKey = rhs.m_decorKey;
119 m_renounced = rhs.m_renounced;
120 m_decorated = rhs.m_decorated;
127 * @brief Move operator.
129 template <class T, class D>
130 WriteDecorHandle<T, D>& WriteDecorHandle<T, D>::operator= (WriteDecorHandle&& rhs)
133 *static_cast<Base*>(this) = std::move (rhs);
134 m_acc = std::move (rhs.m_acc);
135 m_decorKey = std::move (rhs.m_decorKey);
136 m_renounced = rhs.m_renounced;
137 m_decorated = rhs.m_decorated;
138 rhs.m_decorated = false;
145 * @brief Is the referenced container present in SG?
147 * Note that this tests for the presence of the _container_,
148 * not for the decoration.
150 * Const method; the handle does not change as a result of this.
152 template <class T, class D>
153 bool WriteDecorHandle<T, D>::isPresent() const
155 return Base::isPresent();
160 * @brief Explicitly set the event store.
161 * @param store The new event store.
163 * This implicitly does a reset().
165 * We need to override this so that the setting gets made on the container
168 template <class T, class D>
169 StatusCode WriteDecorHandle<T, D>::setProxyDict (IProxyDict* store)
172 return Base::setProxyDict (store);
177 * @brief Fetch the variable for one element, as a reference.
178 * @param e The element for which to fetch the variable.
180 template <class T, class D>
181 typename WriteDecorHandle<T, D>::reference_type
182 WriteDecorHandle<T, D>::operator() (const AuxElement& e)
184 // Ensure that the element we're given is actually an element
185 // of the container we're writing.
186 if (e.container() != this->vectorData()) {
188 throwExcBadDecorElement (Gaudi::DataHandle::Writer,
193 else if (!m_decorated) {
194 makeDecor (e.container());
201 * @brief Fetch the variable for one element, as a reference.
202 * @param index The index of the desired element.
204 * This looks up the variable in the object referenced by this handle.
205 * For a standalone object, pass an index of 0.
207 template <class T, class D>
208 typename WriteDecorHandle<T, D>::reference_type
209 WriteDecorHandle<T, D>::operator() (size_t i)
211 const AuxVectorData* avd = this->vectorData();
212 if (!m_decorated) makeDecor (avd);
213 return m_acc (*avd, i);
218 * @brief Get a pointer to the start of the auxiliary data array,
219 * for the referenced object.
221 template <class T, class D>
222 template <class POINTER_TYPE /*= container_pointer_type*/,
223 typename /*= std::enable_if_t<!std::is_void_v<POINTER_TYPE> >*/ >
225 WriteDecorHandle<T, D>::getDecorationArray()
227 const AuxVectorData* avd = this->vectorData();
228 if (!m_decorated) makeDecor (avd);
229 return m_acc.getDecorationArray (*avd);
234 * @brief Get a span over the auxilary data array,
235 * for the referenced object.
237 template <class T, class D>
239 WriteDecorHandle<T, D>::getDecorationSpan() -> span
241 const AuxVectorData* avd = this->vectorData();
242 if (!m_decorated) makeDecor (avd);
243 return m_acc.getDecorationSpan (*avd);
248 * @brief Test to see if this variable exists in the store,
249 * for the referenced object.
251 template <class T, class D>
253 bool WriteDecorHandle<T, D>::isAvailable()
255 return vectorData()->isAvailable (m_acc.auxid());
260 * @brief Return the aux id for this variable.
262 template <class T, class D>
263 SG::auxid_t WriteDecorHandle<T, D>::auxid() const
265 return m_acc.auxid();
270 * @brief Return the mode (read/write/update) for this handle.
272 template <class T, class D>
274 Gaudi::DataHandle::Mode WriteDecorHandle<T, D>::mode() const
276 return Gaudi::DataHandle::Writer;
281 * @brief Return the name of the decoration alias (CONT.DECOR).
283 template <class T, class D>
285 const std::string& WriteDecorHandle<T, D>::decorKey() const
292 * @brief Create the decoration if it doesn't actually exist yet.
293 * Also create the decoration alias in SG (unless this handle
294 * has been renounced).
295 * @param avd The AuxVectorData instance we're decorating.
296 * (May not be the same as this->vectorData() if the
297 * handle has been renounced.)
299 template <class T, class D>
300 void WriteDecorHandle<T, D>::makeDecor (const AuxVectorData* avd)
303 if (avd->size_v() > 0) {
304 m_acc.getDecorationSpan (*avd);
307 this->alias (WriteHandleKey<T> (this->m_decorKey)).ignore();
314 * @brief Return the referenced object as a @c SG::AuxVectorData.
315 * Specialization for the case of a standalone object
316 * (@c T derives from @c SG::AuxElement).
318 template <class T, class D>
319 const SG::AuxVectorData* WriteDecorHandle<T, D>::vectorData (std::true_type)
321 return (*this)->container();
326 * @brief Return the referenced object as a @c SG::AuxVectorData.
327 * Specialization for the case of a container
328 * (@c T does not derive from @c SG::AuxElement).
330 template <class T, class D>
331 const SG::AuxVectorData* WriteDecorHandle<T, D>::vectorData (std::false_type)
338 * @brief Return the referenced object as a @c SG::AuxVectorData.
340 * If @c T is a container object, then this should be the object itself.
341 * But if it is a standalone object, deriving from @c SG::AuxElement,
342 * then we need to call container() on the object.
344 template <class T, class D>
345 const SG::AuxVectorData* WriteDecorHandle<T, D>::vectorData()
347 return vectorData (typename std::is_base_of<SG::AuxElement, T>::type());
352 * @brief Return a @c WriteDecorHandle referencing @c key.
353 * @param key The key object holding the clid/key/store.
355 * This will raise an exception if the StoreGate key is blank,
356 * or if the event store cannot be found.
358 * The type of the decoration must be included as an explicit template parameter:
361 * auto handle = SG::makeHandle<float> (key);
364 * Note that @c D comes first in the argument list. It's given explicitly,
365 * while @c T is inferred from @c key.
367 template <class D, class T>
368 WriteDecorHandle<T, D> makeHandle (const WriteDecorHandleKey<T>& key)
370 return WriteDecorHandle<T, D> (key);
375 * @brief Return a @c WriteDecorHandle referencing @c key for an explicit context.
376 * @param key The key object holding the clid/key/store.
377 * @param ctx The event context.
379 * This will raise an exception if the StoreGate key is blank,
380 * or if the event store cannot be found.
382 * If the default event store has been requested, then the thread-specific
383 * store from the event context will be used.
385 * The type of the decoration must be included as an explicit template parameter:
388 * auto handle = SG::makeHandle<float> (key, ctx);
391 * Note that @c D comes first in the argument list. It's given explicitly,
392 * while @c T is inferred from @c key.
394 template <class D, class T>
395 WriteDecorHandle<T, D> makeHandle (const WriteDecorHandleKey<T>& key,
396 const EventContext& ctx)
398 return WriteDecorHandle<T, D> (key, ctx);
403 * @brief These two signatures are to catch cases where the explicit
404 * template argument is omitted from the @c makeHandle call
405 * and give an error tailored to that. Otherwise, the @c makeHandle
406 * call for @c ReadHandle would match, potentially giving a much
407 * more confusing error.
410 void makeHandle (const WriteDecorHandleKey<T>& /*key*/)
412 // If you see an error from here, you've forgotten the explicit template
413 // argument to @c makeHandle giving the decoration type.
414 // See the examples of @c makeHandle above.
415 return T::makeHandleForDecorationsRequiresExplicitTemplateArgument();
418 void makeHandle (const WriteDecorHandleKey<T>& /*key*/,
419 const EventContext& /*ctx*/)
421 // If you see an error from here, you've forgotten the explicit template
422 // argument to @c makeHandle giving the decoration type.
423 // See the examples of @c makeHandle above.
424 return T::makeHandleForDecorationsRequiresExplicitTemplateArgument();