2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
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.
11 #ifndef STOREGATE_SG_WRITEHANDLE_ICC
12 #define STOREGATE_SG_WRITEHANDLE_ICC 1
15 #include "StoreGate/exceptions.h"
16 #include "AthenaKernel/ClassID_traits.h"
17 #include "AthenaKernel/errorcheck.h"
24 //************************************************************************
30 * @brief Default constructor.
32 * The handle will not be usable until a non-blank key is assigned.
36 WriteHandle<T>::WriteHandle()
37 : VarHandleBase(ClassID_traits<T>::ID(), Gaudi::DataHandle::Writer)
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.
49 WriteHandle<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)
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.
64 WriteHandle<T>::WriteHandle(const std::string& sgkey,
65 const EventContext& ctx)
66 : WriteHandle(sgkey, StoreID::storeName(StoreID::EVENT_STORE), ctx)
72 * @brief Constructor specifying the key as a string, with context.
73 * @param sgkey StoreGate key of the referenced object.
74 * @param storename Name of the referenced event store.
75 * @param ctx The event context.
79 WriteHandle<T>::WriteHandle(const std::string& sgkey,
80 const std::string& storename,
81 const EventContext& ctx)
82 : VarHandleBase( ClassID_traits<T>::ID(),
83 sgkey, Gaudi::DataHandle::Writer, storename, &ctx )
89 * @brief Constructor from a WriteHandleKey.
90 * @param key The key object holding the clid/key/store.
92 * This will raise an exception if the StoreGate key is blank,
93 * or if the event store cannot be found.
97 WriteHandle<T>::WriteHandle (const WriteHandleKey<T>& key)
98 : VarHandleBase (key, nullptr)
104 * @brief Constructor from a WriteHandleKey and an explicit event context.
105 * @param key The key object holding the clid/key.
106 * @param ctx The event context.
108 * This will raise an exception if the StoreGate key is blank,
109 * or if the event store cannot be found.
111 * If the default event store has been requested, then the thread-specific
112 * store from the event context will be used.
116 WriteHandle<T>::WriteHandle (const WriteHandleKey<T>& key,
117 const EventContext& ctx)
118 : VarHandleBase (key, &ctx)
120 // cppcheck-suppress missingReturn; false positive
125 * @brief Copy constructor.
129 WriteHandle<T>::WriteHandle(const WriteHandle& h)
136 * @brief Move constructor.
139 WriteHandle<T>::WriteHandle(WriteHandle&& h)
140 : VarHandleBase(std::move(h))
142 m_lockAuxPending = h.m_lockAuxPending;
143 h.m_lockAuxPending = nullptr;
148 * @brief Assignment operator.
153 // m_lockAuxPending not copied --- want lifetime to stay with the
155 // cppcheck-suppress operatorEqVarError
156 WriteHandle<T>::operator= (const WriteHandle& h)
159 this->VarHandleBase::operator=(h);
165 * @brief Move operator.
170 WriteHandle<T>::operator= (WriteHandle&& h)
173 this->VarHandleBase::operator=(std::move(h));
174 m_lockAuxPending = h.m_lockAuxPending;
175 h.m_lockAuxPending = nullptr;
184 * Lock an aux object if m_lockAuxPending is true.
187 WriteHandle<T>::~WriteHandle()
189 if (m_lockAuxPending) {
190 m_lockAuxPending->setConst();
195 //************************************************************************
196 // Deference. These all return only the cached pointer.
201 * @brief Dereference the pointer.
202 * Returns the cached pointer. Throws ExcNullWriteHandle if null.
206 typename WriteHandle<T>::pointer_type
207 WriteHandle<T>::operator->()
209 return WriteHandle<T>::checkedCachedPtr();
214 * @brief Dereference the pointer.
215 * Returns the cached pointer. Throws ExcNullWriteHandle if null.
219 typename WriteHandle<T>::reference_type
220 WriteHandle<T>::operator*()
222 return *WriteHandle<T>::checkedCachedPtr();
227 * @brief Dereference the pointer.
228 * Returns the cached pointer.
232 typename WriteHandle<T>::const_pointer_type
233 WriteHandle<T>::cptr() const
235 return reinterpret_cast<pointer_type>(this->m_ptr);
240 * @brief Dereference the pointer.
241 * Returns the cached pointer.
245 typename WriteHandle<T>::pointer_type
246 WriteHandle<T>::ptr()
253 * @brief Return the cached pointer directly; no lookup.
257 typename WriteHandle<T>::pointer_type
258 WriteHandle<T>::cachedPtr()
260 return reinterpret_cast<pointer_type>(this->m_ptr);
265 * @brief Can the handle be successfully dereferenced?
269 bool WriteHandle<T>::isValid()
271 return this->m_ptr != nullptr;
275 //************************************************************************
280 * @brief Record a const object to the store.
281 * @param data The object to record.
286 WriteHandle<T>::WriteHandle::record (std::unique_ptr<T> data)
288 return this->doRecord (std::move(data), true, false);
293 * @brief Record a non-const object to the store.
294 * @param data The object to record.
295 * @param isConst If true, record the object as const.
300 WriteHandle<T>::WriteHandle::recordNonConst (std::unique_ptr<T> data)
302 return this->doRecord (std::move(data), false, false);
307 * @brief Record a const object and its auxiliary store to the store.
308 * @param data The object to record.
309 * @param auxstore Auxiliary store object.
312 template <class AUXSTORE>
315 WriteHandle<T>::WriteHandle::record (std::unique_ptr<T> data,
316 std::unique_ptr<AUXSTORE> auxstore)
318 return record (std::move(data), std::move(auxstore), true);
323 * @brief Record a non-const object and its auxiliary store to the store.
324 * @param data The object to record.
325 * @param auxstore Auxiliary store object.
328 template <class AUXSTORE>
331 WriteHandle<T>::WriteHandle::recordNonConst (std::unique_ptr<T> data,
332 std::unique_ptr<AUXSTORE> auxstore)
334 return record (std::move(data), std::move(auxstore), false);
339 * @brief Record a const shared DataObject to the store.
340 * @param data The object to record.
342 * The event store takes shared ownership of the object.
347 WriteHandle<T>::record (SG::DataObjectSharedPtr<T> data)
349 return this->doRecord (std::move(data), true, false);
354 * @brief Record a non-const shared DataObject to the store.
355 * @param data The object to record.
357 * The event store takes shared ownership of the object.
362 WriteHandle<T>::recordNonConst (SG::DataObjectSharedPtr<T> data)
364 return this->doRecord (std::move(data), false, false);
369 * @brief Record an object to the store.
370 * @param data The object to record.
371 * @param returnExisting Allow an existing object?
373 * Unlike record(), this does not change the handle object.
374 * That means that one will not be able to get the object back
375 * by dereferencing the handle.
376 * Returns the object placed in the store, or nullptr if there
378 * If there was already an object in the store with the given key,
379 * then return null, unless @c returnExisting is true, in which case
380 * return success. In either case, @c data is destroyed.
384 typename WriteHandle<T>::const_pointer_type
385 WriteHandle<T>::put (std::unique_ptr<T> data,
386 bool returnExisting /*= false*/) const
388 IProxyDict* store = nullptr;
389 return doPut (nullptr, std::move(data), returnExisting, store);
394 * @brief Record an object to the store.
395 * @param data The object to record.
396 * @param returnExisting Allow an existing object?
398 * Unlike record(), this does not change the handle object.
399 * That means that one will not be able to get the object back
400 * by dereferencing the handle.
401 * Returns the object placed in the store, or nullptr if there
403 * If there was already an object in the store with the given key,
404 * then return null, unless @c returnExisting is true, in which case
405 * return success. In either case, @c data is destroyed.
409 typename WriteHandle<T>::const_pointer_type
410 WriteHandle<T>::put (std::unique_ptr<const T> data,
411 bool returnExisting /*= false*/) const
413 IProxyDict* store = nullptr;
414 return doPut (nullptr, std::move(data), returnExisting, store);
419 * @brief Record an object to the store.
420 * @param data The object to record.
421 * @param returnExisting Allow an existing object?
423 * Unlike record(), this does not change the handle object.
424 * That means that one will not be able to get the object back
425 * by dereferencing the handle.
426 * Returns the object placed in the store, or nullptr if there
428 * If there was already an object in the store with the given key,
429 * then return null, unless @c returnExisting is true, in which case
430 * return success. In either case, @c data is destroyed.
434 typename WriteHandle<T>::const_pointer_type
435 WriteHandle<T>::put (std::unique_ptr<const ConstDataVector<T> > data,
436 bool returnExisting /*= false*/) const
438 IProxyDict* store = nullptr;
439 std::unique_ptr<const T> coll (data.release()->asDataVector());
440 return doPut (nullptr, std::move(coll), returnExisting, store);
445 * @brief Record an object to the store.
446 * @param ctx The event context to use.
447 * @param data The object to record.
448 * @param returnExisting Allow an existing object?
450 * Unlike record(), this does not change the handle object.
451 * That means that one will not be able to get the object back
452 * by dereferencing the handle.
453 * Returns the object placed in the store, or nullptr if there
455 * If there was already an object in the store with the given key,
456 * then return null, unless @c returnExisting is true, in which case
457 * return success. In either case, @c data is destroyed.
461 typename WriteHandle<T>::const_pointer_type
462 WriteHandle<T>::put (const EventContext& ctx,
463 std::unique_ptr<const ConstDataVector<T> > data,
464 bool returnExisting /*= false*/) const
466 IProxyDict* store = nullptr;
467 std::unique_ptr<const T> coll (data.release()->asDataVector());
468 return doPut (&ctx, std::move(coll), returnExisting, store);
473 * @brief Record an object to the store.
474 * @param ctx The event context to use.
475 * @param data The object to record.
476 * @param returnExisting Allow an existing object?
478 * Unlike record(), this does not change the handle object.
479 * That means that one will not be able to get the object back
480 * by dereferencing the handle.
481 * Returns the object placed in the store, or nullptr if there
483 * If there was already an object in the store with the given key,
484 * then return null, unless @c returnExisting is true, in which case
485 * return success. In either case, @c data is destroyed.
489 typename WriteHandle<T>::const_pointer_type
490 WriteHandle<T>::put (const EventContext& ctx,
491 std::unique_ptr<T> data,
492 bool returnExisting /*= false*/) const
494 IProxyDict* store = nullptr;
495 return doPut (&ctx, std::move(data), returnExisting, store);
500 * @brief Record an object to the store.
501 * @param ctx The event context to use.
502 * @param data The object to record.
503 * @param returnExisting Allow an existing object?
505 * Unlike record(), this does not change the handle object.
506 * That means that one will not be able to get the object back
507 * by dereferencing the handle.
508 * Returns the object placed in the store, or nullptr if there
510 * If there was already an object in the store with the given key,
511 * then return null, unless @c returnExisting is true, in which case
512 * return success. In either case, @c data is destroyed.
516 typename WriteHandle<T>::const_pointer_type
517 WriteHandle<T>::put (const EventContext& ctx,
518 std::unique_ptr<const T> data,
519 bool returnExisting /*= false*/) const
521 IProxyDict* store = nullptr;
522 return doPut (&ctx, std::move(data), returnExisting, store);
527 * @brief Record an object to the store.
528 * @param data The object to record.
530 * Unlike record(), this does not change the handle object.
531 * That means that one will not be able to get the object back
532 * by dereferencing the handle.
533 * Returns the object placed in the store, or nullptr if there
536 * The event store takes shared ownership of the object.
540 typename WriteHandle<T>::const_pointer_type
541 WriteHandle<T>::put (SG::DataObjectSharedPtr<T> data) const
543 IProxyDict* store = nullptr;
544 return doPut (nullptr, std::move(data), false, store);
549 * @brief Record an object to the store.
550 * @param ctx The event context to use.
551 * @param data The object to record.
553 * Unlike record(), this does not change the handle object.
554 * That means that one will not be able to get the object back
555 * by dereferencing the handle.
556 * Returns the object placed in the store, or nullptr if there
559 * The event store takes shared ownership of the object.
563 typename WriteHandle<T>::const_pointer_type
564 WriteHandle<T>::put (const EventContext& ctx,
565 SG::DataObjectSharedPtr<T> data) const
567 IProxyDict* store = nullptr;
568 return doPut (&ctx, std::move(data), false, store);
573 * @brief Record an object and its auxiliary store to the store.
574 * @param data The object to record.
575 * @param auxstore Auxiliary store object.
577 * Unlike record(), this does not change the handle object.
578 * That means that one will not be able to get the object back
579 * by dereferencing the handle.
580 * Returns the object placed in the store, or nullptr if there
582 * If there was already an object in the store with the given key,
583 * then return null, and the objects passed in are destroyed.
586 template <class AUXSTORE>
587 typename WriteHandle<T>::const_pointer_type
588 WriteHandle<T>::put (std::unique_ptr<T> data,
589 std::unique_ptr<AUXSTORE> auxstore) const
591 return doPut (nullptr, std::move(data), std::move(auxstore));
597 * @brief Record an object and its auxiliary store to the store.
598 * @param data The object to record.
599 * @param auxstore Auxiliary store object.
601 * Unlike record(), this does not change the handle object.
602 * That means that one will not be able to get the object back
603 * by dereferencing the handle.
604 * Returns the object placed in the store, or nullptr if there
606 * If there was already an object in the store with the given key,
607 * then return null, and the objects passed in are destroyed.
609 * Unlike the version taking unique_ptr<T>, this does not alter the
610 * store pointer of @c data.
613 template <class AUXSTORE>
614 typename WriteHandle<T>::const_pointer_type
615 WriteHandle<T>::put (std::unique_ptr<const T> data,
616 std::unique_ptr<const AUXSTORE> auxstore) const
618 return doPut (nullptr, std::move(data), std::move(auxstore));
623 * @brief Record an object and its auxiliary store to the store.
624 * @param ctx The event context to use.
625 * @param data The object to record.
626 * @param auxstore Auxiliary store object.
628 * Unlike record(), this does not change the handle object.
629 * That means that one will not be able to get the object back
630 * by dereferencing the handle.
631 * Returns the object placed in the store, or nullptr if there
633 * If there was already an object in the store with the given key,
634 * then return null, and the objects passed in are destroyed.
637 template <class AUXSTORE>
638 typename WriteHandle<T>::const_pointer_type
639 WriteHandle<T>::put (const EventContext& ctx,
640 std::unique_ptr<T> data,
641 std::unique_ptr<AUXSTORE> auxstore) const
643 return doPut (&ctx, std::move(data), std::move(auxstore));
648 * @brief Record an object and its auxiliary store to the store.
649 * @param ctx The event context to use.
650 * @param data The object to record.
651 * @param auxstore Auxiliary store object.
653 * Unlike record(), this does not change the handle object.
654 * That means that one will not be able to get the object back
655 * by dereferencing the handle.
656 * Returns the object placed in the store, or nullptr if there
658 * If there was already an object in the store with the given key,
659 * then return null, and the objects passed in are destroyed.
661 * Unlike the version taking unique_ptr<T>, this does not alter the
662 * store pointer of @c data.
665 template <class AUXSTORE>
666 typename WriteHandle<T>::const_pointer_type
667 WriteHandle<T>::put (const EventContext& ctx,
668 std::unique_ptr<const T> data,
669 std::unique_ptr<const AUXSTORE> auxstore) const
671 return doPut (&ctx, std::move(data), std::move(auxstore));
676 * @brief Alternate notation for record. Records a non-const object.
677 * @param data Object to record.
679 * Throws an exception on failure.
683 WriteHandle<T>::operator= (std::unique_ptr<T> data)
685 if (recordNonConst (std::move(data)).isFailure()) {
686 throw std::runtime_error ("WriteHandle<T>::operator=(unique_ptr) Record failed.");
693 * @brief Make an alias.
694 * @param key Alternate key by which the referenced object should be known.
696 * The current handle should be valid and referencing an object
697 * (i.e., @c record should have been called on it).
699 * The object will also be known by the name given in @c key.
702 StatusCode WriteHandle<T>::alias (const WriteHandleKey<T>& key)
704 return symLink_impl (this->clid(), key.key());
709 * @brief Make an explicit link.
710 * @param key Alternate clid by which the referenced object
711 * should be known. The SG key must match the key of the
714 * You should generally not be using this!
716 * The current handle should be valid and referencing an object
717 * (i.e., @c record should have been called on it).
719 * This makes a symlink: the object will be retrievable
720 * as a different type.
722 * Note that if @c T and @c @U are related via @c SG_BASE and/or
723 * @c DATAVECTOR_BASE, then you shouldn't need to explicitly make a symlink;
724 * that should happen automatically.
726 * If a @c U* is not convertable to a @c T* via C++ rules, then you likely
727 * will be, at best, relying on undefined behavior. You will probably
728 * get warnings from the undefined behavior sanitizer when if you try
729 * to dereference the @c U*.
731 * This usage is here mainly to assist in migrating some existing
732 * patterns to MT. You should think several times before using
737 StatusCode WriteHandle<T>::symLink (const WriteHandleKey<U>& other)
739 if (this->key() != other.key()) {
740 REPORT_ERROR (StatusCode::FAILURE)
741 << "symLink: SG keys do not match: " << other.key() << " vs "
743 return StatusCode::FAILURE;
745 return symLink_impl (other.clid(), other.key());
750 * @brief Return the cached pointer directly.
752 * If it is null, throw ExcNullWriteHandle.
755 typename WriteHandle<T>::pointer_type
756 WriteHandle<T>::checkedCachedPtr()
759 throwExcNullWriteHandle (clid(), key(), store());
765 * @brief Helper for record.
766 * @param data The object to record.
767 * @param isConst If true, record the object as const.
768 * @param returnExisting Allow an existing object.
772 StatusCode WriteHandle<T>::doRecord (U data,
776 typedef typename U::element_type elt_t;
778 // make sure the BaseInfo(Base) structure is initialized
779 SG::BaseInfo<elt_t>::baseinfo();
781 // If s_isConst is set for this type, then we want to automatically
782 // make it const when recorded.
783 bool allowMods = !isConst;
784 if (ClassID_traits<elt_t>::s_isConst)
787 void* dataPtr(data.get());
788 std::unique_ptr<DataObject> dobj (SG::asStorable (std::move (data)));
789 return this->record_impl (std::move(dobj), dataPtr, allowMods, returnExisting);
794 * @brief Helper for put.
795 * @param ctx The event context, or nullptr to use the current context.
796 * @param data The object to record.
797 * @param returnExisting Allow an existing object.
798 * @param[out] store The store being used.
800 * Unlike record(), this does not change the handle object.
801 * That means that will not be able to get the object back
802 * by dereferencing the handle.
803 * Returns the object placed in the store, or nullptr if there
805 * If there was already an object in the store with the given key,
806 * then return null, unless @c returnExisting is true, in which case
807 * return success. In either case, @c data is destroyed.
811 typename WriteHandle<T>::const_pointer_type
812 WriteHandle<T>::doPut (const EventContext* ctx,
815 IProxyDict* & store) const
817 //typedef typename U::element_type elt_t;
820 // make sure the BaseInfo(Base) structure is initialized
821 SG::BaseInfo<elt_t>::baseinfo();
823 const void* dataPtr = data.get();
824 std::unique_ptr<DataObject> dobj (SG::asStorable (std::move (data)));
825 return reinterpret_cast<const T*>
826 (this->put_impl (ctx, std::move(dobj), dataPtr, false, returnExisting, store));
831 * @brief Helper for recording an object and its auxiliary store to the store.
832 * @param ctx The event context, or nullptr to use the current context.
833 * @param data The object to record.
834 * @param auxstore Auxiliary store object.
836 * Unlike record(), this does not change the handle object.
837 * That means that will not be able to get the object back
838 * by dereferencing the handle.
839 * Returns the object placed in the store, or nullptr if there
841 * If there was already an object in the store with the given key,
842 * then return null, and the objects passed in are destroyed.
845 template <class AUXSTORE>
846 typename WriteHandle<T>::const_pointer_type
847 WriteHandle<T>::doPut (const EventContext* ctx,
848 std::unique_ptr<T> data,
849 std::unique_ptr<AUXSTORE> auxstore) const
853 // If there's no store association, do it now.
854 if (data->getStore() == nullptr)
855 data->setStore (auxstore.get());
857 IProxyDict* store = nullptr;
858 const T* ptr = this->doPut (ctx, std::move(data), false, store);
859 if (!ptr) return nullptr;
861 SG::DataObjectSharedPtr<DataObject> dobj
862 (SG::asStorable (std::move (auxstore)));
863 SG::DataProxy* proxy = store->recordObject (std::move(dobj),
864 this->name() + "Aux.",
868 REPORT_ERROR (StatusCode::FAILURE)
869 << "recordObject of aux store failed";
871 // If we've failed here, then the aux store object has been deleted,
872 // but not the primary object. Null out the store pointer to prevent
873 // having a dangling pointer to a deleted object.
874 dref.setStore (static_cast<SG::IConstAuxStore*>(nullptr));
883 * @brief Helper for recording an object and its auxiliary store to the store.
884 * @param ctx The event context, or nullptr to use the current context.
885 * @param data The object to record.
886 * @param auxstore Auxiliary store object.
888 * Unlike record(), this does not change the handle object.
889 * That means that will not be able to get the object back
890 * by dereferencing the handle.
891 * Returns the object placed in the store, or nullptr if there
893 * If there was already an object in the store with the given key,
894 * then return null, and the objects passed in are destroyed.
897 template <class AUXSTORE>
898 typename WriteHandle<T>::const_pointer_type
899 WriteHandle<T>::doPut (const EventContext* ctx,
900 std::unique_ptr<const T> data,
901 std::unique_ptr<const AUXSTORE> auxstore) const
903 IProxyDict* store = nullptr;
904 const T* ptr = this->doPut (ctx, std::move(data), false, store);
905 if (!ptr) return nullptr;
907 SG::DataObjectSharedPtr<DataObject> dobj
908 (SG::asStorable (std::move (auxstore)));
909 SG::DataProxy* proxy = store->recordObject (std::move(dobj),
910 this->name() + "Aux.",
914 REPORT_ERROR (StatusCode::FAILURE)
915 << "recordObject of aux store failed";
924 * @brief Record an object and its auxiliary store to the store.
925 * @param data The object to record.
926 * @param auxstore Auxiliary store object.
927 * @param isConst If true, record the objects as const.
930 template <class AUXSTORE>
932 WriteHandle<T>::record (std::unique_ptr<T> data,
933 std::unique_ptr<AUXSTORE> auxstore,
938 // If there's no store association, do it now.
939 if (data->getStore() == nullptr)
940 data->setStore (auxstore.get());
943 // Temporarily clear the store association, in order to prevent
944 // the aux store from being locked at this point.
945 IAuxStore* store = dref.getStore();
947 dref.setStore (static_cast<SG::IAuxStore*>(nullptr));
948 CHECK (this->record(std::move(data)));
949 // Deliberately not using RAII here. If there is an error,
950 // then the object referenced by data will be deleted.
951 dref.setStore (store);
954 CHECK (this->recordNonConst(std::move(data)));
956 // Store and proxy must be valid if we get to this point.
958 SG::DataObjectSharedPtr<DataObject> dobj
959 (SG::asStorable (std::move (auxstore)));
960 SG::DataProxy* proxy = m_store->recordObject (std::move(dobj),
961 this->name() + "Aux.",
965 REPORT_ERROR (StatusCode::FAILURE)
966 << "recordObject of aux store failed";
968 // If we've failed here, then the aux store object has been deleted,
969 // but not the primary object. Null out the store pointer to prevent
970 // having a dangling pointer to a deleted object.
971 dref.setStore (static_cast<SG::IConstAuxStore*>(nullptr));
972 return StatusCode::FAILURE;
975 if (m_proxy->isConst())
976 m_lockAuxPending = proxy;
978 return StatusCode::SUCCESS;
983 * @brief Return a @c WriteHandle referencing @c key.
984 * @param key The key object holding the clid/key/store.
986 * This will raise an exception if the StoreGate key is blank,
987 * or if the event store cannot be found.
990 WriteHandle<T> makeHandle (const WriteHandleKey<T>& key)
992 return WriteHandle<T> (key);
997 * @brief Return a @c WriteHandle referencing @c key for an explicit context.
998 * @param key The key object holding the clid/key/store.
999 * @param ctx The event context.
1001 * This will raise an exception if the StoreGate key is blank,
1002 * or if the event store cannot be found.
1004 * If the default event store has been requested, then the thread-specific
1005 * store from the event context will be used.
1008 WriteHandle<T> makeHandle (const WriteHandleKey<T>& key,
1009 const EventContext& ctx)
1011 return WriteHandle<T> (key, ctx);
1015 } /* namespace SG */
1018 #endif //> !STOREGATE_SG_WRITEHANDLE_ICC