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