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.
36WriteHandle<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.
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)
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.
64WriteHandle<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.
79WriteHandle<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.
97WriteHandle<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.
116WriteHandle<T>::WriteHandle (const WriteHandleKey<T>& key,
117 const EventContext& ctx)
118 : VarHandleBase (key, &ctx)
120 // cppcheck-suppress missingReturn; false positive
125 * @brief Copy constructor.
129WriteHandle<T>::WriteHandle(const WriteHandle& h)
136 * @brief Move constructor.
139WriteHandle<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
156WriteHandle<T>::operator= (const WriteHandle& h)
159 this->VarHandleBase::operator=(h);
165 * @brief Move operator.
170WriteHandle<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.
187WriteHandle<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.
206typename WriteHandle<T>::pointer_type
207WriteHandle<T>::operator->()
209 return WriteHandle<T>::checkedCachedPtr();
214 * @brief Dereference the pointer.
215 * Returns the cached pointer. Throws ExcNullWriteHandle if null.
219typename WriteHandle<T>::reference_type
220WriteHandle<T>::operator*()
222 return *WriteHandle<T>::checkedCachedPtr();
227 * @brief Dereference the pointer.
228 * Returns the cached pointer.
232typename WriteHandle<T>::const_pointer_type
233WriteHandle<T>::cptr() const
235 return reinterpret_cast<pointer_type>(this->m_ptr);
240 * @brief Dereference the pointer.
241 * Returns the cached pointer.
245typename WriteHandle<T>::pointer_type
253 * @brief Return the cached pointer directly; no lookup.
257typename WriteHandle<T>::pointer_type
258WriteHandle<T>::cachedPtr()
260 return reinterpret_cast<pointer_type>(this->m_ptr);
265 * @brief Can the handle be successfully dereferenced?
269bool 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.
286WriteHandle<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.
300WriteHandle<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.
312template <class AUXSTORE>
315WriteHandle<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.
328template <class AUXSTORE>
331WriteHandle<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.
345template <std::derived_from<DataObject> DOBJ>
346requires std::convertible_to<DOBJ*, T*>
349WriteHandle<T>::record (SG::DataObjectSharedPtr<DOBJ> data)
351 return this->doRecord (std::move(data), true, false);
356 * @brief Record a non-const shared DataObject to the store.
357 * @param data The object to record.
359 * The event store takes shared ownership of the object.
362template <std::derived_from<DataObject> DOBJ>
363requires std::convertible_to<DOBJ*, T*>
366WriteHandle<T>::recordNonConst (SG::DataObjectSharedPtr<DOBJ> data)
368 return this->doRecord (std::move(data), false, false);
373 * @brief Record an object to the store.
374 * @param data The object to record.
375 * @param returnExisting Allow an existing object?
377 * Unlike record(), this does not change the handle object.
378 * That means that one will not be able to get the object back
379 * by dereferencing the handle.
380 * Returns the object placed in the store, or nullptr if there
382 * If there was already an object in the store with the given key,
383 * then return null, unless @c returnExisting is true, in which case
384 * return success. In either case, @c data is destroyed.
388typename WriteHandle<T>::const_pointer_type
389WriteHandle<T>::put (std::unique_ptr<T> data,
390 bool returnExisting /*= false*/) const
392 IProxyDict* store = nullptr;
393 return doPut (nullptr, std::move(data), returnExisting, store);
398 * @brief Record an object to the store.
399 * @param data The object to record.
400 * @param returnExisting Allow an existing object?
402 * Unlike record(), this does not change the handle object.
403 * That means that one will not be able to get the object back
404 * by dereferencing the handle.
405 * Returns the object placed in the store, or nullptr if there
407 * If there was already an object in the store with the given key,
408 * then return null, unless @c returnExisting is true, in which case
409 * return success. In either case, @c data is destroyed.
413typename WriteHandle<T>::const_pointer_type
414WriteHandle<T>::put (std::unique_ptr<const T> data,
415 bool returnExisting /*= false*/) const
417 IProxyDict* store = nullptr;
418 return doPut (nullptr, std::move(data), returnExisting, store);
423 * @brief Record an object to the store.
424 * @param data The object to record.
425 * @param returnExisting Allow an existing object?
427 * Unlike record(), this does not change the handle object.
428 * That means that one will not be able to get the object back
429 * by dereferencing the handle.
430 * Returns the object placed in the store, or nullptr if there
432 * If there was already an object in the store with the given key,
433 * then return null, unless @c returnExisting is true, in which case
434 * return success. In either case, @c data is destroyed.
438typename WriteHandle<T>::const_pointer_type
439WriteHandle<T>::put (std::unique_ptr<const ConstDataVector<T> > data,
440 bool returnExisting /*= false*/) const
442 IProxyDict* store = nullptr;
443 std::unique_ptr<const T> coll (data.release()->asDataVector());
444 return doPut (nullptr, std::move(coll), returnExisting, store);
449 * @brief Record an object to the store.
450 * @param ctx The event context to use.
451 * @param data The object to record.
452 * @param returnExisting Allow an existing object?
454 * Unlike record(), this does not change the handle object.
455 * That means that one will not be able to get the object back
456 * by dereferencing the handle.
457 * Returns the object placed in the store, or nullptr if there
459 * If there was already an object in the store with the given key,
460 * then return null, unless @c returnExisting is true, in which case
461 * return success. In either case, @c data is destroyed.
465typename WriteHandle<T>::const_pointer_type
466WriteHandle<T>::put (const EventContext& ctx,
467 std::unique_ptr<const ConstDataVector<T> > data,
468 bool returnExisting /*= false*/) const
470 IProxyDict* store = nullptr;
471 std::unique_ptr<const T> coll (data.release()->asDataVector());
472 return doPut (&ctx, std::move(coll), returnExisting, store);
477 * @brief Record an object to the store.
478 * @param ctx The event context to use.
479 * @param data The object to record.
480 * @param returnExisting Allow an existing object?
482 * Unlike record(), this does not change the handle object.
483 * That means that one will not be able to get the object back
484 * by dereferencing the handle.
485 * Returns the object placed in the store, or nullptr if there
487 * If there was already an object in the store with the given key,
488 * then return null, unless @c returnExisting is true, in which case
489 * return success. In either case, @c data is destroyed.
493typename WriteHandle<T>::const_pointer_type
494WriteHandle<T>::put (const EventContext& ctx,
495 std::unique_ptr<T> data,
496 bool returnExisting /*= false*/) const
498 IProxyDict* store = nullptr;
499 return doPut (&ctx, std::move(data), returnExisting, store);
504 * @brief Record an object to the store.
505 * @param ctx The event context to use.
506 * @param data The object to record.
507 * @param returnExisting Allow an existing object?
509 * Unlike record(), this does not change the handle object.
510 * That means that one will not be able to get the object back
511 * by dereferencing the handle.
512 * Returns the object placed in the store, or nullptr if there
514 * If there was already an object in the store with the given key,
515 * then return null, unless @c returnExisting is true, in which case
516 * return success. In either case, @c data is destroyed.
520typename WriteHandle<T>::const_pointer_type
521WriteHandle<T>::put (const EventContext& ctx,
522 std::unique_ptr<const T> data,
523 bool returnExisting /*= false*/) const
525 IProxyDict* store = nullptr;
526 return doPut (&ctx, std::move(data), returnExisting, store);
531 * @brief Record an object to the store.
532 * @param data The object to record.
534 * Unlike record(), this does not change the handle object.
535 * That means that one will not be able to get the object back
536 * by dereferencing the handle.
537 * Returns the object placed in the store, or nullptr if there
540 * The event store takes shared ownership of the object.
543template <std::derived_from<DataObject> DOBJ>
544requires std::convertible_to<DOBJ*, T*>
546typename WriteHandle<T>::const_pointer_type
547WriteHandle<T>::put (SG::DataObjectSharedPtr<DOBJ> data) const
549 IProxyDict* store = nullptr;
550 return doPut (nullptr, std::move(data), false, store);
555 * @brief Record an object to the store.
556 * @param ctx The event context to use.
557 * @param data The object to record.
559 * Unlike record(), this does not change the handle object.
560 * That means that one will not be able to get the object back
561 * by dereferencing the handle.
562 * Returns the object placed in the store, or nullptr if there
565 * The event store takes shared ownership of the object.
568template <std::derived_from<DataObject> DOBJ>
569requires std::convertible_to<DOBJ*, T*>
571typename WriteHandle<T>::const_pointer_type
572WriteHandle<T>::put (const EventContext& ctx,
573 SG::DataObjectSharedPtr<DOBJ> data) const
575 IProxyDict* store = nullptr;
576 return doPut (&ctx, std::move(data), false, store);
581 * @brief Record an object and its auxiliary store to the store.
582 * @param data The object to record.
583 * @param auxstore Auxiliary store object.
585 * Unlike record(), this does not change the handle object.
586 * That means that one will not be able to get the object back
587 * by dereferencing the handle.
588 * Returns the object placed in the store, or nullptr if there
590 * If there was already an object in the store with the given key,
591 * then return null, and the objects passed in are destroyed.
594template <class AUXSTORE>
595typename WriteHandle<T>::const_pointer_type
596WriteHandle<T>::put (std::unique_ptr<T> data,
597 std::unique_ptr<AUXSTORE> auxstore) const
599 return doPut (nullptr, std::move(data), std::move(auxstore));
605 * @brief Record an object and its auxiliary store to the store.
606 * @param data The object to record.
607 * @param auxstore Auxiliary store object.
609 * Unlike record(), this does not change the handle object.
610 * That means that one will not be able to get the object back
611 * by dereferencing the handle.
612 * Returns the object placed in the store, or nullptr if there
614 * If there was already an object in the store with the given key,
615 * then return null, and the objects passed in are destroyed.
617 * Unlike the version taking unique_ptr<T>, this does not alter the
618 * store pointer of @c data.
621template <class AUXSTORE>
622typename WriteHandle<T>::const_pointer_type
623WriteHandle<T>::put (std::unique_ptr<const T> data,
624 std::unique_ptr<const AUXSTORE> auxstore) const
626 return doPut (nullptr, std::move(data), std::move(auxstore));
631 * @brief Record an object and its auxiliary store to the store.
632 * @param ctx The event context to use.
633 * @param data The object to record.
634 * @param auxstore Auxiliary store object.
636 * Unlike record(), this does not change the handle object.
637 * That means that one will not be able to get the object back
638 * by dereferencing the handle.
639 * Returns the object placed in the store, or nullptr if there
641 * If there was already an object in the store with the given key,
642 * then return null, and the objects passed in are destroyed.
645template <class AUXSTORE>
646typename WriteHandle<T>::const_pointer_type
647WriteHandle<T>::put (const EventContext& ctx,
648 std::unique_ptr<T> data,
649 std::unique_ptr<AUXSTORE> auxstore) const
651 return doPut (&ctx, std::move(data), std::move(auxstore));
656 * @brief Record an object and its auxiliary store to the store.
657 * @param ctx The event context to use.
658 * @param data The object to record.
659 * @param auxstore Auxiliary store object.
661 * Unlike record(), this does not change the handle object.
662 * That means that one will not be able to get the object back
663 * by dereferencing the handle.
664 * Returns the object placed in the store, or nullptr if there
666 * If there was already an object in the store with the given key,
667 * then return null, and the objects passed in are destroyed.
669 * Unlike the version taking unique_ptr<T>, this does not alter the
670 * store pointer of @c data.
673template <class AUXSTORE>
674typename WriteHandle<T>::const_pointer_type
675WriteHandle<T>::put (const EventContext& ctx,
676 std::unique_ptr<const T> data,
677 std::unique_ptr<const AUXSTORE> auxstore) const
679 return doPut (&ctx, std::move(data), std::move(auxstore));
684 * @brief Alternate notation for record. Records a non-const object.
685 * @param data Object to record.
687 * Throws an exception on failure.
691WriteHandle<T>::operator= (std::unique_ptr<T> data)
693 if (recordNonConst (std::move(data)).isFailure()) {
694 throw std::runtime_error ("WriteHandle<T>::operator=(unique_ptr) Record failed.");
701 * @brief Make an alias.
702 * @param key Alternate key by which the referenced object should be known.
704 * The current handle should be valid and referencing an object
705 * (i.e., @c record should have been called on it).
707 * The object will also be known by the name given in @c key.
710StatusCode WriteHandle<T>::alias (const WriteHandleKey<T>& key)
712 return symLink_impl (this->clid(), key.key());
717 * @brief Make an explicit link.
718 * @param key Alternate clid by which the referenced object
719 * should be known. The SG key must match the key of the
722 * You should generally not be using this!
724 * The current handle should be valid and referencing an object
725 * (i.e., @c record should have been called on it).
727 * This makes a symlink: the object will be retrievable
728 * as a different type.
730 * Note that if @c T and @c @U are related via @c SG_BASE and/or
731 * @c DATAVECTOR_BASE, then you shouldn't need to explicitly make a symlink;
732 * that should happen automatically.
734 * If a @c U* is not convertable to a @c T* via C++ rules, then you likely
735 * will be, at best, relying on undefined behavior. You will probably
736 * get warnings from the undefined behavior sanitizer when if you try
737 * to dereference the @c U*.
739 * This usage is here mainly to assist in migrating some existing
740 * patterns to MT. You should think several times before using
745StatusCode WriteHandle<T>::symLink (const WriteHandleKey<U>& other)
747 if (this->key() != other.key()) {
748 REPORT_ERROR (StatusCode::FAILURE)
749 << "symLink: SG keys do not match: " << other.key() << " vs "
751 return StatusCode::FAILURE;
753 return symLink_impl (other.clid(), other.key());
758 * @brief Return the cached pointer directly.
760 * If it is null, throw ExcNullWriteHandle.
763typename WriteHandle<T>::pointer_type
764WriteHandle<T>::checkedCachedPtr()
767 throwExcNullWriteHandle (clid(), key(), store());
773 * @brief Helper for record.
774 * @param data The object to record.
775 * @param isConst If true, record the object as const.
776 * @param returnExisting Allow an existing object.
780StatusCode WriteHandle<T>::doRecord (U data,
784 typedef typename U::element_type elt_t;
786 // make sure the BaseInfo(Base) structure is initialized
787 SG::BaseInfo<elt_t>::baseinfo();
789 // If s_isConst is set for this type, then we want to automatically
790 // make it const when recorded.
791 bool allowMods = !isConst;
792 if (ClassID_traits<elt_t>::s_isConst)
795 void* dataPtr(data.get());
796 std::unique_ptr<DataObject> dobj (SG::asStorable (std::move (data)));
797 return this->record_impl (std::move(dobj), dataPtr, allowMods, returnExisting);
802 * @brief Helper for put.
803 * @param ctx The event context, or nullptr to use the current context.
804 * @param data The object to record.
805 * @param returnExisting Allow an existing object.
806 * @param[out] store The store being used.
808 * Unlike record(), this does not change the handle object.
809 * That means that will not be able to get the object back
810 * by dereferencing the handle.
811 * Returns the object placed in the store, or nullptr if there
813 * If there was already an object in the store with the given key,
814 * then return null, unless @c returnExisting is true, in which case
815 * return success. In either case, @c data is destroyed.
819typename WriteHandle<T>::const_pointer_type
820WriteHandle<T>::doPut (const EventContext* ctx,
823 IProxyDict* & store) const
825 //typedef typename U::element_type elt_t;
828 // make sure the BaseInfo(Base) structure is initialized
829 SG::BaseInfo<elt_t>::baseinfo();
831 const void* dataPtr = data.get();
832 std::unique_ptr<DataObject> dobj (SG::asStorable (std::move (data)));
833 return reinterpret_cast<const T*>
834 (this->put_impl (ctx, std::move(dobj), dataPtr, false, returnExisting, store));
839 * @brief Helper for recording an object and its auxiliary store to the store.
840 * @param ctx The event context, or nullptr to use the current context.
841 * @param data The object to record.
842 * @param auxstore Auxiliary store object.
844 * Unlike record(), this does not change the handle object.
845 * That means that will not be able to get the object back
846 * by dereferencing the handle.
847 * Returns the object placed in the store, or nullptr if there
849 * If there was already an object in the store with the given key,
850 * then return null, and the objects passed in are destroyed.
853template <class AUXSTORE>
854typename WriteHandle<T>::const_pointer_type
855WriteHandle<T>::doPut (const EventContext* ctx,
856 std::unique_ptr<T> data,
857 std::unique_ptr<AUXSTORE> auxstore) const
861 // If there's no store association, do it now.
862 if (data->getStore() == nullptr)
863 data->setStore (auxstore.get());
865 IProxyDict* store = nullptr;
866 const T* ptr = this->doPut (ctx, std::move(data), false, store);
867 if (!ptr) return nullptr;
869 SG::DataObjectSharedPtr<DataObject> dobj
870 (SG::asStorable (std::move (auxstore)));
871 SG::DataProxy* proxy = store->recordObject (std::move(dobj),
872 this->name() + "Aux.",
876 REPORT_ERROR (StatusCode::FAILURE)
877 << "recordObject of aux store failed";
879 // If we've failed here, then the aux store object has been deleted,
880 // but not the primary object. Null out the store pointer to prevent
881 // having a dangling pointer to a deleted object.
882 dref.setStore (static_cast<SG::IConstAuxStore*>(nullptr));
891 * @brief Helper for recording an object and its auxiliary store to the store.
892 * @param ctx The event context, or nullptr to use the current context.
893 * @param data The object to record.
894 * @param auxstore Auxiliary store object.
896 * Unlike record(), this does not change the handle object.
897 * That means that will not be able to get the object back
898 * by dereferencing the handle.
899 * Returns the object placed in the store, or nullptr if there
901 * If there was already an object in the store with the given key,
902 * then return null, and the objects passed in are destroyed.
905template <class AUXSTORE>
906typename WriteHandle<T>::const_pointer_type
907WriteHandle<T>::doPut (const EventContext* ctx,
908 std::unique_ptr<const T> data,
909 std::unique_ptr<const AUXSTORE> auxstore) const
911 IProxyDict* store = nullptr;
912 const T* ptr = this->doPut (ctx, std::move(data), false, store);
913 if (!ptr) return nullptr;
915 SG::DataObjectSharedPtr<DataObject> dobj
916 (SG::asStorable (std::move (auxstore)));
917 SG::DataProxy* proxy = store->recordObject (std::move(dobj),
918 this->name() + "Aux.",
922 REPORT_ERROR (StatusCode::FAILURE)
923 << "recordObject of aux store failed";
932 * @brief Record an object and its auxiliary store to the store.
933 * @param data The object to record.
934 * @param auxstore Auxiliary store object.
935 * @param isConst If true, record the objects as const.
938template <class AUXSTORE>
940WriteHandle<T>::record (std::unique_ptr<T> data,
941 std::unique_ptr<AUXSTORE> auxstore,
946 // If there's no store association, do it now.
947 if (data->getStore() == nullptr)
948 data->setStore (auxstore.get());
951 // Temporarily clear the store association, in order to prevent
952 // the aux store from being locked at this point.
953 IAuxStore* store = dref.getStore();
955 dref.setStore (static_cast<SG::IAuxStore*>(nullptr));
956 CHECK (this->record(std::move(data)));
957 // Deliberately not using RAII here. If there is an error,
958 // then the object referenced by data will be deleted.
959 dref.setStore (store);
962 CHECK (this->recordNonConst(std::move(data)));
964 // Store and proxy must be valid if we get to this point.
966 SG::DataObjectSharedPtr<DataObject> dobj
967 (SG::asStorable (std::move (auxstore)));
968 SG::DataProxy* proxy = m_store->recordObject (std::move(dobj),
969 this->name() + "Aux.",
973 REPORT_ERROR (StatusCode::FAILURE)
974 << "recordObject of aux store failed";
976 // If we've failed here, then the aux store object has been deleted,
977 // but not the primary object. Null out the store pointer to prevent
978 // having a dangling pointer to a deleted object.
979 dref.setStore (static_cast<SG::IConstAuxStore*>(nullptr));
980 return StatusCode::FAILURE;
983 if (m_proxy->isConst())
984 m_lockAuxPending = proxy;
986 return StatusCode::SUCCESS;
991 * @brief Return a @c WriteHandle referencing @c key.
992 * @param key The key object holding the clid/key/store.
994 * This will raise an exception if the StoreGate key is blank,
995 * or if the event store cannot be found.
998WriteHandle<T> makeHandle (const WriteHandleKey<T>& key)
1000 return WriteHandle<T> (key);
1005 * @brief Return a @c WriteHandle referencing @c key for an explicit context.
1006 * @param key The key object holding the clid/key/store.
1007 * @param ctx The event context.
1009 * This will raise an exception if the StoreGate key is blank,
1010 * or if the event store cannot be found.
1012 * If the default event store has been requested, then the thread-specific
1013 * store from the event context will be used.
1016WriteHandle<T> makeHandle (const WriteHandleKey<T>& key,
1017 const EventContext& ctx)
1019 return WriteHandle<T> (key, ctx);
1026#endif //> !STOREGATE_SG_WRITEHANDLE_ICC