ATLAS Offline Software
Loading...
Searching...
No Matches
StoreGate/StoreGate/WriteHandle.icc
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4/**
5 * @file StoreGate/WriteHandle.icc
6 * @author S. Binet, P. Calafiura, scott snyder <snyder@bnl.gov>
7 * @date Updated: Feb, 2016
8 * @brief Handle class for recording to StoreGate.
9 */
10
11#ifndef STOREGATE_SG_WRITEHANDLE_ICC
12#define STOREGATE_SG_WRITEHANDLE_ICC 1
13
14
15#include "StoreGate/exceptions.h"
16#include "AthenaKernel/ClassID_traits.h"
17#include "AthenaKernel/errorcheck.h"
18#include <stdexcept>
19
20
21namespace SG {
22
23
24//************************************************************************
25// Constructors, etc.
26//
27
28
29/**
30 * @brief Default constructor.
31 *
32 * The handle will not be usable until a non-blank key is assigned.
33 */
34template <class T>
35inline
36WriteHandle<T>::WriteHandle()
37 : VarHandleBase(ClassID_traits<T>::ID(), Gaudi::DataHandle::Writer)
38{
39}
40
41
42/**
43 * @brief Constructor specifying the key as a string.
44 * @param sgkey StoreGate key of the referenced object.
45 * @param storename Name of the referenced event store.
46 */
47template <class T>
48inline
49WriteHandle<T>::WriteHandle (const std::string& sgkey,
50 const std::string& storename /* ="StoreGateSvc"*/)
51 : VarHandleBase (ClassID_traits<T>::ID(), sgkey,
52 Gaudi::DataHandle::Writer, storename, nullptr)
53{
54}
55
56
57/**
58 * @brief Constructor specifying the key as a string, with context.
59 * @param sgkey StoreGate key of the referenced object.
60 * @param ctx The event context.
61 */
62template <class T>
63inline
64WriteHandle<T>::WriteHandle(const std::string& sgkey, const EventContext& ctx)
65 : WriteHandle(sgkey, StoreID::storeName(StoreID::EVENT_STORE), ctx)
66{
67}
68
69
70/**
71 * @brief Constructor specifying the key as a string, with data store.
72 * @param sgkey StoreGate key of the referenced object.
73 * @param sg Data store.
74 */
75template <class T>
76inline
77WriteHandle<T>::WriteHandle(const std::string& sgkey, IProxyDict* sg)
78 : VarHandleBase(ClassID_traits<T>::ID(), sgkey, Gaudi::DataHandle::Writer, sg)
79{
80 // cppcheck-suppress missingReturn; false positive
81}
82
83
84/**
85 * @brief Constructor specifying the key as a string, with context.
86 * @param sgkey StoreGate key of the referenced object.
87 * @param storename Name of the referenced event store.
88 * @param ctx The event context.
89 */
90template <class T>
91inline
92WriteHandle<T>::WriteHandle(const std::string& sgkey,
93 const std::string& storename,
94 const EventContext& ctx)
95 : VarHandleBase( ClassID_traits<T>::ID(),
96 sgkey, Gaudi::DataHandle::Writer, storename, &ctx )
97{
98}
99
100
101/**
102 * @brief Constructor from a WriteHandleKey.
103 * @param key The key object holding the clid/key/store.
104 *
105 * This will raise an exception if the StoreGate key is blank,
106 * or if the event store cannot be found.
107 */
108template <class T>
109inline
110WriteHandle<T>::WriteHandle (const WriteHandleKey<T>& key)
111 : VarHandleBase (key, nullptr)
112{
113}
114
115
116/**
117 * @brief Constructor from a WriteHandleKey and an explicit event context.
118 * @param key The key object holding the clid/key.
119 * @param ctx The event context.
120 *
121 * This will raise an exception if the StoreGate key is blank,
122 * or if the event store cannot be found.
123 *
124 * If the default event store has been requested, then the thread-specific
125 * store from the event context will be used.
126 */
127template <class T>
128inline
129WriteHandle<T>::WriteHandle (const WriteHandleKey<T>& key,
130 const EventContext& ctx)
131 : VarHandleBase (key, &ctx)
132{
133 // cppcheck-suppress missingReturn; false positive
134}
135
136
137/**
138 * @brief Copy constructor.
139 */
140template <class T>
141inline
142WriteHandle<T>::WriteHandle(const WriteHandle& h)
143 : VarHandleBase(h)
144{
145}
146
147
148/**
149 * @brief Move constructor.
150 */
151template <class T>
152WriteHandle<T>::WriteHandle(WriteHandle&& h) noexcept
153 : VarHandleBase(std::move(h))
154{
155 m_lockAuxPending = h.m_lockAuxPending;
156 h.m_lockAuxPending = nullptr;
157}
158
159
160/**
161 * @brief Assignment operator.
162 */
163template <class T>
164inline
165WriteHandle<T>&
166// m_lockAuxPending not copied --- want lifetime to stay with the
167// original WH.
168// cppcheck-suppress operatorEqVarError
169WriteHandle<T>::operator= (const WriteHandle& h)
170{
171 if (this != &h)
172 this->VarHandleBase::operator=(h);
173 return *this;
174}
175
176
177/**
178 * @brief Move operator.
179 */
180template <class T>
181inline
182WriteHandle<T>&
183WriteHandle<T>::operator= (WriteHandle&& h) noexcept
184{
185 if (this != &h) {
186 this->VarHandleBase::operator=(std::move(h));
187 m_lockAuxPending = h.m_lockAuxPending;
188 h.m_lockAuxPending = nullptr;
189 }
190 return *this;
191}
192
193
194/**
195 * @brief Destructor.
196 *
197 * Lock an aux object if m_lockAuxPending is true.
198 */
199template <class T>
200WriteHandle<T>::~WriteHandle()
201{
202 if (m_lockAuxPending) {
203 m_lockAuxPending->setConst();
204 }
205}
206
207
208//************************************************************************
209// Deference. These all return only the cached pointer.
210//
211
212
213/**
214 * @brief Dereference the pointer.
215 * Returns the cached pointer. Throws ExcNullWriteHandle if null.
216 */
217template <class T>
218inline
219typename WriteHandle<T>::pointer_type
220WriteHandle<T>::operator->()
221{
222 return WriteHandle<T>::checkedCachedPtr();
223}
224
225
226/**
227 * @brief Dereference the pointer.
228 * Returns the cached pointer. Throws ExcNullWriteHandle if null.
229 */
230template <class T>
231inline
232typename WriteHandle<T>::reference_type
233WriteHandle<T>::operator*()
234{
235 return *WriteHandle<T>::checkedCachedPtr();
236}
237
238
239/**
240 * @brief Dereference the pointer.
241 * Returns the cached pointer.
242 */
243template <class T>
244inline
245typename WriteHandle<T>::const_pointer_type
246WriteHandle<T>::cptr() const
247{
248 return reinterpret_cast<pointer_type>(this->m_ptr);
249}
250
251
252/**
253 * @brief Dereference the pointer.
254 * Returns the cached pointer.
255 */
256template <class T>
257inline
258typename WriteHandle<T>::pointer_type
259WriteHandle<T>::ptr()
260{
261 return cachedPtr();
262}
263
264
265/**
266 * @brief Return the cached pointer directly; no lookup.
267 */
268template <class T>
269inline
270typename WriteHandle<T>::pointer_type
271WriteHandle<T>::cachedPtr()
272{
273 return reinterpret_cast<pointer_type>(this->m_ptr);
274}
275
276
277/**
278 * @brief Can the handle be successfully dereferenced?
279 */
280template <class T>
281inline
282bool WriteHandle<T>::isValid()
283{
284 return this->m_ptr != nullptr;
285}
286
287
288//************************************************************************
289// Record.
290
291
292/**
293 * @brief Record a const object to the store.
294 * @param data The object to record.
295 */
296template <class T>
297inline
298StatusCode
299WriteHandle<T>::WriteHandle::record (std::unique_ptr<T> data)
300{
301 return this->doRecord (std::move(data), true, false);
302}
303
304
305/**
306 * @brief Record a non-const object to the store.
307 * @param data The object to record.
308 * @param isConst If true, record the object as const.
309 */
310template <class T>
311inline
312StatusCode
313WriteHandle<T>::WriteHandle::recordNonConst (std::unique_ptr<T> data)
314{
315 return this->doRecord (std::move(data), false, false);
316}
317
318
319/**
320 * @brief Record a const object and its auxiliary store to the store.
321 * @param data The object to record.
322 * @param auxstore Auxiliary store object.
323 */
324template <class T>
325template <class AUXSTORE>
326inline
327StatusCode
328WriteHandle<T>::WriteHandle::record (std::unique_ptr<T> data,
329 std::unique_ptr<AUXSTORE> auxstore)
330{
331 return record (std::move(data), std::move(auxstore), true);
332}
333
334
335/**
336 * @brief Record a non-const object and its auxiliary store to the store.
337 * @param data The object to record.
338 * @param auxstore Auxiliary store object.
339 */
340template <class T>
341template <class AUXSTORE>
342inline
343StatusCode
344WriteHandle<T>::WriteHandle::recordNonConst (std::unique_ptr<T> data,
345 std::unique_ptr<AUXSTORE> auxstore)
346{
347 return record (std::move(data), std::move(auxstore), false);
348}
349
350
351/**
352 * @brief Record a const shared DataObject to the store.
353 * @param data The object to record.
354 *
355 * The event store takes shared ownership of the object.
356 */
357template <class T>
358template <std::derived_from<DataObject> DOBJ>
359requires std::convertible_to<DOBJ*, T*>
360inline
361StatusCode
362WriteHandle<T>::record (SG::DataObjectSharedPtr<DOBJ> data)
363{
364 return this->doRecord (std::move(data), true, false);
365}
366
367
368/**
369 * @brief Record a non-const shared DataObject to the store.
370 * @param data The object to record.
371 *
372 * The event store takes shared ownership of the object.
373 */
374template <class T>
375template <std::derived_from<DataObject> DOBJ>
376requires std::convertible_to<DOBJ*, T*>
377inline
378StatusCode
379WriteHandle<T>::recordNonConst (SG::DataObjectSharedPtr<DOBJ> data)
380{
381 return this->doRecord (std::move(data), false, false);
382}
383
384
385/**
386 * @brief Record an object to the store.
387 * @param data The object to record.
388 * @param returnExisting Allow an existing object?
389 *
390 * Unlike record(), this does not change the handle object.
391 * That means that one will not be able to get the object back
392 * by dereferencing the handle.
393 * Returns the object placed in the store, or nullptr if there
394 * was an error.
395 * If there was already an object in the store with the given key,
396 * then return null, unless @c returnExisting is true, in which case
397 * return success. In either case, @c data is destroyed.
398 */
399template <class T>
400inline
401typename WriteHandle<T>::const_pointer_type
402WriteHandle<T>::put (std::unique_ptr<T> data,
403 bool returnExisting /*= false*/) const
404{
405 IProxyDict* store = nullptr;
406 return doPut (nullptr, std::move(data), returnExisting, store);
407}
408
409
410/**
411 * @brief Record an object to the store.
412 * @param data The object to record.
413 * @param returnExisting Allow an existing object?
414 *
415 * Unlike record(), this does not change the handle object.
416 * That means that one will not be able to get the object back
417 * by dereferencing the handle.
418 * Returns the object placed in the store, or nullptr if there
419 * was an error.
420 * If there was already an object in the store with the given key,
421 * then return null, unless @c returnExisting is true, in which case
422 * return success. In either case, @c data is destroyed.
423 */
424template <class T>
425inline
426typename WriteHandle<T>::const_pointer_type
427WriteHandle<T>::put (std::unique_ptr<const T> data,
428 bool returnExisting /*= false*/) const
429{
430 IProxyDict* store = nullptr;
431 return doPut (nullptr, std::move(data), returnExisting, store);
432}
433
434
435/**
436 * @brief Record an object to the store.
437 * @param data The object to record.
438 * @param returnExisting Allow an existing object?
439 *
440 * Unlike record(), this does not change the handle object.
441 * That means that one will not be able to get the object back
442 * by dereferencing the handle.
443 * Returns the object placed in the store, or nullptr if there
444 * was an error.
445 * If there was already an object in the store with the given key,
446 * then return null, unless @c returnExisting is true, in which case
447 * return success. In either case, @c data is destroyed.
448 */
449template <class T>
450inline
451typename WriteHandle<T>::const_pointer_type
452WriteHandle<T>::put (std::unique_ptr<const ConstDataVector<T> > data,
453 bool returnExisting /*= false*/) const
454{
455 IProxyDict* store = nullptr;
456 std::unique_ptr<const T> coll (data.release()->asDataVector());
457 return doPut (nullptr, std::move(coll), returnExisting, store);
458}
459
460
461/**
462 * @brief Record an object to the store.
463 * @param ctx The event context to use.
464 * @param data The object to record.
465 * @param returnExisting Allow an existing object?
466 *
467 * Unlike record(), this does not change the handle object.
468 * That means that one will not be able to get the object back
469 * by dereferencing the handle.
470 * Returns the object placed in the store, or nullptr if there
471 * was an error.
472 * If there was already an object in the store with the given key,
473 * then return null, unless @c returnExisting is true, in which case
474 * return success. In either case, @c data is destroyed.
475 */
476template <class T>
477inline
478typename WriteHandle<T>::const_pointer_type
479WriteHandle<T>::put (const EventContext& ctx,
480 std::unique_ptr<const ConstDataVector<T> > data,
481 bool returnExisting /*= false*/) const
482{
483 IProxyDict* store = nullptr;
484 std::unique_ptr<const T> coll (data.release()->asDataVector());
485 return doPut (&ctx, std::move(coll), returnExisting, store);
486}
487
488
489/**
490 * @brief Record an object to the store.
491 * @param ctx The event context to use.
492 * @param data The object to record.
493 * @param returnExisting Allow an existing object?
494 *
495 * Unlike record(), this does not change the handle object.
496 * That means that one will not be able to get the object back
497 * by dereferencing the handle.
498 * Returns the object placed in the store, or nullptr if there
499 * was an error.
500 * If there was already an object in the store with the given key,
501 * then return null, unless @c returnExisting is true, in which case
502 * return success. In either case, @c data is destroyed.
503 */
504template <class T>
505inline
506typename WriteHandle<T>::const_pointer_type
507WriteHandle<T>::put (const EventContext& ctx,
508 std::unique_ptr<T> data,
509 bool returnExisting /*= false*/) const
510{
511 IProxyDict* store = nullptr;
512 return doPut (&ctx, std::move(data), returnExisting, store);
513}
514
515
516/**
517 * @brief Record an object to the store.
518 * @param ctx The event context to use.
519 * @param data The object to record.
520 * @param returnExisting Allow an existing object?
521 *
522 * Unlike record(), this does not change the handle object.
523 * That means that one will not be able to get the object back
524 * by dereferencing the handle.
525 * Returns the object placed in the store, or nullptr if there
526 * was an error.
527 * If there was already an object in the store with the given key,
528 * then return null, unless @c returnExisting is true, in which case
529 * return success. In either case, @c data is destroyed.
530 */
531template <class T>
532inline
533typename WriteHandle<T>::const_pointer_type
534WriteHandle<T>::put (const EventContext& ctx,
535 std::unique_ptr<const T> data,
536 bool returnExisting /*= false*/) const
537{
538 IProxyDict* store = nullptr;
539 return doPut (&ctx, std::move(data), returnExisting, store);
540}
541
542
543/**
544 * @brief Record an object to the store.
545 * @param data The object to record.
546 *
547 * Unlike record(), this does not change the handle object.
548 * That means that one will not be able to get the object back
549 * by dereferencing the handle.
550 * Returns the object placed in the store, or nullptr if there
551 * was an error.
552 *
553 * The event store takes shared ownership of the object.
554 */
555template <class T>
556template <std::derived_from<DataObject> DOBJ>
557requires std::convertible_to<DOBJ*, T*>
558inline
559typename WriteHandle<T>::const_pointer_type
560WriteHandle<T>::put (SG::DataObjectSharedPtr<DOBJ> data) const
561{
562 IProxyDict* store = nullptr;
563 return doPut (nullptr, std::move(data), false, store);
564}
565
566
567/**
568 * @brief Record an object to the store.
569 * @param ctx The event context to use.
570 * @param data The object to record.
571 *
572 * Unlike record(), this does not change the handle object.
573 * That means that one will not be able to get the object back
574 * by dereferencing the handle.
575 * Returns the object placed in the store, or nullptr if there
576 * was an error.
577 *
578 * The event store takes shared ownership of the object.
579 */
580template <class T>
581template <std::derived_from<DataObject> DOBJ>
582requires std::convertible_to<DOBJ*, T*>
583inline
584typename WriteHandle<T>::const_pointer_type
585WriteHandle<T>::put (const EventContext& ctx,
586 SG::DataObjectSharedPtr<DOBJ> data) const
587{
588 IProxyDict* store = nullptr;
589 return doPut (&ctx, std::move(data), false, store);
590}
591
592
593/**
594 * @brief Record an object and its auxiliary store to the store.
595 * @param data The object to record.
596 * @param auxstore Auxiliary store object.
597 *
598 * Unlike record(), this does not change the handle object.
599 * That means that one will not be able to get the object back
600 * by dereferencing the handle.
601 * Returns the object placed in the store, or nullptr if there
602 * was an error.
603 * If there was already an object in the store with the given key,
604 * then return null, and the objects passed in are destroyed.
605 */
606template <class T>
607template <class AUXSTORE>
608typename WriteHandle<T>::const_pointer_type
609WriteHandle<T>::put (std::unique_ptr<T> data,
610 std::unique_ptr<AUXSTORE> auxstore) const
611{
612 return doPut (nullptr, std::move(data), std::move(auxstore));
613}
614
615
616
617/**
618 * @brief Record an object and its auxiliary store to the store.
619 * @param data The object to record.
620 * @param auxstore Auxiliary store object.
621 *
622 * Unlike record(), this does not change the handle object.
623 * That means that one will not be able to get the object back
624 * by dereferencing the handle.
625 * Returns the object placed in the store, or nullptr if there
626 * was an error.
627 * If there was already an object in the store with the given key,
628 * then return null, and the objects passed in are destroyed.
629 *
630 * Unlike the version taking unique_ptr<T>, this does not alter the
631 * store pointer of @c data.
632 */
633template <class T>
634template <class AUXSTORE>
635typename WriteHandle<T>::const_pointer_type
636WriteHandle<T>::put (std::unique_ptr<const T> data,
637 std::unique_ptr<const AUXSTORE> auxstore) const
638{
639 return doPut (nullptr, std::move(data), std::move(auxstore));
640}
641
642
643/**
644 * @brief Record an object and its auxiliary store to the store.
645 * @param ctx The event context to use.
646 * @param data The object to record.
647 * @param auxstore Auxiliary store object.
648 *
649 * Unlike record(), this does not change the handle object.
650 * That means that one will not be able to get the object back
651 * by dereferencing the handle.
652 * Returns the object placed in the store, or nullptr if there
653 * was an error.
654 * If there was already an object in the store with the given key,
655 * then return null, and the objects passed in are destroyed.
656 */
657template <class T>
658template <class AUXSTORE>
659typename WriteHandle<T>::const_pointer_type
660WriteHandle<T>::put (const EventContext& ctx,
661 std::unique_ptr<T> data,
662 std::unique_ptr<AUXSTORE> auxstore) const
663{
664 return doPut (&ctx, std::move(data), std::move(auxstore));
665}
666
667
668/**
669 * @brief Record an object and its auxiliary store to the store.
670 * @param ctx The event context to use.
671 * @param data The object to record.
672 * @param auxstore Auxiliary store object.
673 *
674 * Unlike record(), this does not change the handle object.
675 * That means that one will not be able to get the object back
676 * by dereferencing the handle.
677 * Returns the object placed in the store, or nullptr if there
678 * was an error.
679 * If there was already an object in the store with the given key,
680 * then return null, and the objects passed in are destroyed.
681 *
682 * Unlike the version taking unique_ptr<T>, this does not alter the
683 * store pointer of @c data.
684 */
685template <class T>
686template <class AUXSTORE>
687typename WriteHandle<T>::const_pointer_type
688WriteHandle<T>::put (const EventContext& ctx,
689 std::unique_ptr<const T> data,
690 std::unique_ptr<const AUXSTORE> auxstore) const
691{
692 return doPut (&ctx, std::move(data), std::move(auxstore));
693}
694
695
696/**
697 * @brief Alternate notation for record. Records a non-const object.
698 * @param data Object to record.
699 *
700 * Throws an exception on failure.
701 */
702template <class T>
703WriteHandle<T>&
704WriteHandle<T>::operator= (std::unique_ptr<T> data)
705{
706 if (recordNonConst (std::move(data)).isFailure()) {
707 throw std::runtime_error ("WriteHandle<T>::operator=(unique_ptr) Record failed.");
708 }
709 return *this;
710}
711
712
713/**
714 * @brief Make an alias.
715 * @param key Alternate key by which the referenced object should be known.
716 *
717 * The current handle should be valid and referencing an object
718 * (i.e., @c record should have been called on it).
719 *
720 * The object will also be known by the name given in @c key.
721 */
722template <class T>
723StatusCode WriteHandle<T>::alias (const WriteHandleKey<T>& key)
724{
725 return symLink_impl (this->clid(), key.key());
726}
727
728
729/**
730 * @brief Make an explicit link.
731 * @param key Alternate clid by which the referenced object
732 * should be known. The SG key must match the key of the
733 * current handle.
734 *
735 * You should generally not be using this!
736 *
737 * The current handle should be valid and referencing an object
738 * (i.e., @c record should have been called on it).
739 *
740 * This makes a symlink: the object will be retrievable
741 * as a different type.
742 *
743 * Note that if @c T and @c @U are related via @c SG_BASE and/or
744 * @c DATAVECTOR_BASE, then you shouldn't need to explicitly make a symlink;
745 * that should happen automatically.
746 *
747 * If a @c U* is not convertable to a @c T* via C++ rules, then you likely
748 * will be, at best, relying on undefined behavior. You will probably
749 * get warnings from the undefined behavior sanitizer when if you try
750 * to dereference the @c U*.
751 *
752 * This usage is here mainly to assist in migrating some existing
753 * patterns to MT. You should think several times before using
754 * in new code.
755 */
756template <class T>
757template <class U>
758StatusCode WriteHandle<T>::symLink (const WriteHandleKey<U>& other)
759{
760 if (this->key() != other.key()) {
761 REPORT_ERROR (StatusCode::FAILURE)
762 << "symLink: SG keys do not match: " << other.key() << " vs "
763 << this->key();
764 return StatusCode::FAILURE;
765 }
766 return symLink_impl (other.clid(), other.key());
767}
768
769
770/**
771 * @brief Return the cached pointer directly.
772 *
773 * If it is null, throw ExcNullWriteHandle.
774 */
775template <class T>
776typename WriteHandle<T>::pointer_type
777WriteHandle<T>::checkedCachedPtr()
778{
779 if (!m_ptr)
780 throwExcNullWriteHandle (clid(), key(), store());
781 return cachedPtr();
782}
783
784
785/**
786 * @brief Helper for record.
787 * @param data The object to record.
788 * @param isConst If true, record the object as const.
789 * @param returnExisting Allow an existing object.
790 */
791template <class T>
792template <class U>
793StatusCode WriteHandle<T>::doRecord (U data,
794 bool isConst,
795 bool returnExisting)
796{
797 typedef typename U::element_type elt_t;
798
799 // make sure the BaseInfo(Base) structure is initialized
800 SG::BaseInfo<elt_t>::baseinfo();
801
802 // If s_isConst is set for this type, then we want to automatically
803 // make it const when recorded.
804 bool allowMods = !isConst;
805 if (ClassID_traits<elt_t>::s_isConst)
806 allowMods = false;
807
808 void* dataPtr(data.get());
809 std::unique_ptr<DataObject> dobj (SG::asStorable (std::move (data)));
810 return this->record_impl (std::move(dobj), dataPtr, allowMods, returnExisting);
811}
812
813
814/**
815 * @brief Helper for put.
816 * @param ctx The event context, or nullptr to use the current context.
817 * @param data The object to record.
818 * @param returnExisting Allow an existing object.
819 * @param[out] store The store being used.
820 *
821 * Unlike record(), this does not change the handle object.
822 * That means that will not be able to get the object back
823 * by dereferencing the handle.
824 * Returns the object placed in the store, or nullptr if there
825 * was an error.
826 * If there was already an object in the store with the given key,
827 * then return null, unless @c returnExisting is true, in which case
828 * return success. In either case, @c data is destroyed.
829 */
830template <class T>
831template <class U>
832typename WriteHandle<T>::const_pointer_type
833WriteHandle<T>::doPut (const EventContext* ctx,
834 U data,
835 bool returnExisting,
836 IProxyDict* & store) const
837{
838 //typedef typename U::element_type elt_t;
839 typedef T elt_t;
840
841 // make sure the BaseInfo(Base) structure is initialized
842 SG::BaseInfo<elt_t>::baseinfo();
843
844 const void* dataPtr = data.get();
845 std::unique_ptr<DataObject> dobj (SG::asStorable (std::move (data)));
846 return reinterpret_cast<const T*>
847 (this->put_impl (ctx, std::move(dobj), dataPtr, false, returnExisting, store));
848}
849
850
851/**
852 * @brief Helper for recording an object and its auxiliary store to the store.
853 * @param ctx The event context, or nullptr to use the current context.
854 * @param data The object to record.
855 * @param auxstore Auxiliary store object.
856 *
857 * Unlike record(), this does not change the handle object.
858 * That means that will not be able to get the object back
859 * by dereferencing the handle.
860 * Returns the object placed in the store, or nullptr if there
861 * was an error.
862 * If there was already an object in the store with the given key,
863 * then return null, and the objects passed in are destroyed.
864 */
865template <class T>
866template <class AUXSTORE>
867typename WriteHandle<T>::const_pointer_type
868WriteHandle<T>::doPut (const EventContext* ctx,
869 std::unique_ptr<T> data,
870 std::unique_ptr<AUXSTORE> auxstore) const
871{
872 T& dref = *data;
873
874 // If there's no store association, do it now.
875 if (data->getStore() == nullptr)
876 data->setStore (auxstore.get());
877
878 IProxyDict* store = nullptr;
879 const T* ptr = this->doPut (ctx, std::move(data), false, store);
880 if (!ptr) return nullptr;
881
882 SG::DataObjectSharedPtr<DataObject> dobj
883 (SG::asStorable (std::move (auxstore)));
884 SG::DataProxy* proxy = store->recordObject (std::move(dobj),
885 this->name() + "Aux.",
886 false,
887 false);
888 if (!proxy) {
889 REPORT_ERROR (StatusCode::FAILURE)
890 << "recordObject of aux store failed";
891
892 // If we've failed here, then the aux store object has been deleted,
893 // but not the primary object. Null out the store pointer to prevent
894 // having a dangling pointer to a deleted object.
895 dref.setStore (static_cast<SG::IConstAuxStore*>(nullptr));
896 return nullptr;
897 }
898
899 return ptr;
900}
901
902
903/**
904 * @brief Helper for recording an object and its auxiliary store to the store.
905 * @param ctx The event context, or nullptr to use the current context.
906 * @param data The object to record.
907 * @param auxstore Auxiliary store object.
908 *
909 * Unlike record(), this does not change the handle object.
910 * That means that will not be able to get the object back
911 * by dereferencing the handle.
912 * Returns the object placed in the store, or nullptr if there
913 * was an error.
914 * If there was already an object in the store with the given key,
915 * then return null, and the objects passed in are destroyed.
916 */
917template <class T>
918template <class AUXSTORE>
919typename WriteHandle<T>::const_pointer_type
920WriteHandle<T>::doPut (const EventContext* ctx,
921 std::unique_ptr<const T> data,
922 std::unique_ptr<const AUXSTORE> auxstore) const
923{
924 IProxyDict* store = nullptr;
925 const T* ptr = this->doPut (ctx, std::move(data), false, store);
926 if (!ptr) return nullptr;
927
928 SG::DataObjectSharedPtr<DataObject> dobj
929 (SG::asStorable (std::move (auxstore)));
930 SG::DataProxy* proxy = store->recordObject (std::move(dobj),
931 this->name() + "Aux.",
932 false,
933 false);
934 if (!proxy) {
935 REPORT_ERROR (StatusCode::FAILURE)
936 << "recordObject of aux store failed";
937 return nullptr;
938 }
939
940 return ptr;
941}
942
943
944/**
945 * @brief Record an object and its auxiliary store to the store.
946 * @param data The object to record.
947 * @param auxstore Auxiliary store object.
948 * @param isConst If true, record the objects as const.
949 */
950template <class T>
951template <class AUXSTORE>
952StatusCode
953WriteHandle<T>::record (std::unique_ptr<T> data,
954 std::unique_ptr<AUXSTORE> auxstore,
955 bool isConst)
956{
957 T& dref = *data;
958
959 // If there's no store association, do it now.
960 if (data->getStore() == nullptr)
961 data->setStore (auxstore.get());
962
963 if (isConst) {
964 // Temporarily clear the store association, in order to prevent
965 // the aux store from being locked at this point.
966 IAuxStore* store = dref.getStore();
967 if (store)
968 dref.setStore (static_cast<SG::IAuxStore*>(nullptr));
969 CHECK (this->record(std::move(data)));
970 // Deliberately not using RAII here. If there is an error,
971 // then the object referenced by data will be deleted.
972 dref.setStore (store);
973 }
974 else
975 CHECK (this->recordNonConst(std::move(data)));
976
977 // Store and proxy must be valid if we get to this point.
978
979 SG::DataObjectSharedPtr<DataObject> dobj
980 (SG::asStorable (std::move (auxstore)));
981 SG::DataProxy* proxy = m_store->recordObject (std::move(dobj),
982 this->name() + "Aux.",
983 true,
984 false);
985 if (!proxy) {
986 REPORT_ERROR (StatusCode::FAILURE)
987 << "recordObject of aux store failed";
988
989 // If we've failed here, then the aux store object has been deleted,
990 // but not the primary object. Null out the store pointer to prevent
991 // having a dangling pointer to a deleted object.
992 dref.setStore (static_cast<SG::IConstAuxStore*>(nullptr));
993 return StatusCode::FAILURE;
994 }
995
996 if (m_proxy->isConst())
997 m_lockAuxPending = proxy;
998
999 return StatusCode::SUCCESS;
1000}
1001
1002
1003/**
1004 * @brief Return a @c WriteHandle referencing @c key.
1005 * @param key The key object holding the clid/key/store.
1006 *
1007 * This will raise an exception if the StoreGate key is blank,
1008 * or if the event store cannot be found.
1009 */
1010template <class T>
1011WriteHandle<T> makeHandle (const WriteHandleKey<T>& key)
1012{
1013 return WriteHandle<T> (key);
1014}
1015
1016
1017/**
1018 * @brief Return a @c WriteHandle referencing @c key for an explicit context.
1019 * @param key The key object holding the clid/key/store.
1020 * @param ctx The event context.
1021 *
1022 * This will raise an exception if the StoreGate key is blank,
1023 * or if the event store cannot be found.
1024 *
1025 * If the default event store has been requested, then the thread-specific
1026 * store from the event context will be used.
1027 */
1028template <class T>
1029WriteHandle<T> makeHandle (const WriteHandleKey<T>& key,
1030 const EventContext& ctx)
1031{
1032 return WriteHandle<T> (key, ctx);
1033}
1034
1035
1036} /* namespace SG */
1037
1038
1039#endif //> !STOREGATE_SG_WRITEHANDLE_ICC