ATLAS Offline Software
Loading...
Searching...
No Matches
WriteDataReentrant.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
11
12
13#undef NDEBUG
14#include "WriteDataReentrant.h"
15
16#include <list>
17#include <vector>
18
20#include "MyContObj.h"
21#include "MapStringFloat.h"
23
26#include "AthLinks/DataLink.h"
27#include "AthLinks/ElementLink.h"
29
32
34
36{
38
39 // If user did not set a key, use our own name. This cannot be done in the
40 // constructor as "DefaultName" is used during configurable generation (genconf).
41 if (m_dobjKey3.empty()) m_dobjKey3 = name();
42 if (m_pLinkListKey.empty()) m_pLinkListKey = name();
43
44 ATH_MSG_INFO ("in initialize()");
45 ATH_CHECK( m_dobjKey.initialize() );
46 ATH_CHECK( m_dobjKey2.initialize() );
47 ATH_CHECK( m_dobjKey3.initialize() );
48 ATH_CHECK( m_cobjKey.initialize() );
49 ATH_CHECK( m_vFloatKey.initialize() );
50 ATH_CHECK( m_pLinkListKey.initialize() );
51 ATH_CHECK( m_mKey.initialize() );
52 ATH_CHECK( m_linkVectorKey.initialize() );
53 ATH_CHECK( m_testObjectKey.initialize() );
54 ATH_CHECK( m_dobjKeyArray.initialize() );
55
58 return StatusCode::SUCCESS;
59}
60
61// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
62
63StatusCode WriteDataReentrant::execute (const EventContext& ctx) const
64{
65 //this example illustrates how to record objects into the StoreGate(SG)
66 //with and without providing a key
67 //It then covers the new DataLink class and its usage as a persistable
68 //reference among objects in the SG
69 //Finally it shows how to use symlinks to record an object using its
70 //concrete type and its base class(es).
71
72 ATH_MSG_INFO ("in execute()");
73
74 // For algorithms that produce new data objects like this one
75 // the SG works like a bulletin board: the algorithm posts the
76 // new object to the SG (optionally providing a "name" for it).
77 // The SG assigns a unique identifier to the object and puts it on display
78 // alongside others of the same type.
79 // At preset intervals all objects are removed from the board to make room
80 // for new ones and filed.
81
82 // Part 1: Recording objects to SG
84 dobj = std::make_unique<MyDataObj>(1);
85
86 //now we create a second MyDataObj instance...
87 //...try to record it as we did for the first. Since dobj2 is also a
88 //MyDataObj we expect to see an error
89 ATH_MSG_WARNING ("we expect an error message here");
90 EXPECT_EXCEPTION (std::runtime_error,
91 dobj = std::make_unique<MyDataObj>(2));
92 ATH_MSG_WARNING ("end of error message");
93
94 //here we go again...
95 //... but this time we register the dobj3 using this algo name as key
96 auto dobj3 = SG::makeHandle (m_dobjKey3, ctx);
97 dobj3 = std::make_unique<MyDataObj>(3);
98
100 if (m_testObject->refCount() != 1) std::abort();
101 ATH_CHECK( testobj.record (m_testObject) );
102 if (m_testObject->refCount() != 2) std::abort();
103
104 // Writing an array of objects.
105 size_t i = 0;
108 ATH_CHECK( h.record (std::make_unique<MyDataObj> (i+100)) );
109 ++i;
110 }
111
113
114 // Part 2: storing collections in the SG
115
117 ATH_CHECK( cobj.record (std::make_unique<DataVector<MyContObj> >()) );
118 cobj->reserve(10);
119 cobj->push_back (std::make_unique<MyContObj> (11.3, 132));
120 cobj->push_back (std::make_unique<MyContObj> (41.7, 291));
121
122 // as above with a vector of integers
124 vFloat = std::make_unique<std::vector<float> >();
125 vFloat->push_back(1.0);
126 vFloat->push_back(2.0);
127 vFloat->push_back(3.0);
128
130 ATH_CHECK( m.record (std::make_unique<MapStringFloat>()) );
131 (*m)["uno"]=1.0;
132 (*m)["due"]=2.0;
133
135 //
136 // Part 3: Data Links
137 //
138 // Data links are persistable references. Typically they will replace
139 // pointers from one object in the event to another, hence they have
140 // the usual "pointer" syntax (op *, op ->, op !, ...)
141 // (to be pedantic they have the moniker syntax as they don't define ++, --)
142 // For example in Atlfast::Cell
143 // class Cell {
144 // ...
145 // private:
146 // std::vector<const HepMC::Particle*> m_particles;
147 // };
148 // m_particles would become
149 // std::vector<HepMCLink<Particle>::type > m_particles;
150 //
151 // To understand data links it is important to observe that the SG
152 // is not able to identify every single object in the event.
153 // In particular individual elements of a container (the MyContObj
154 // in the vector above or the Particles in McEventCollection) are not
155 // recorded individually into SG, only their owner (the container) is.
156 // For this reason data links are supported by two class templates:
157 // DataLink<DATAOBJ> is a link to a data object i.e. an object
158 // identified by SG
159 // ElementLink<CONTAINER> is a link to an element of a container (which
160 // in turn is a SG data object)
161 // To make a DataLink persistable we need to provide its SG identifier
162 // (its type and key).
163 // To make an ElementLink persistable we need two pieces of information:
164 // i) the SG identifier (type/key) of the data object owning the element
165 // ii) the identifier of the contained object within the owner
166 // For example when we write out a link to the third element of
167 // our vector<float> we want to write the SG id of the vector
168 // and the index (2) of the element in the vector
169 //
170 // Since the indexing mechanism of a container depends on the container
171 // type we need to specialize ElementLink for different containers
172 // Elements of STL sequences (lists, vectors, deques but also DataVector
173 // and DataList) are dealt with automatically.
174 // For other STL or STL-like containers, the data object designer (or the
175 // client must "help" ElementLink identifying the type of container
176 // Three macros in the header StoreGate/DeclareIndexingPolicy.h
177 // are provided to this end:
178 // for sequences use CONTAINER_IS_SEQUENCE( MySequence )
179 // for sets use CONTAINER_IS_SET( MySet )
180 // for maps and related containers use CONTAINER_IS_MAP( MyMap )
181 //
182 // It is also possible to define custom specializations of ElementLink
183 // for custom containers (e.g. GenParticleLink for McEventCollection).
184 //
185 //Enough! Let's now create our first DataLink. It refers to the first
186 // MyDataObj we recorded. DataLink constructors use references
187 // as input arguments
188 //
189 // DataLink referring to a storable object
190 //
191 DataLink<MyDataObj> dobjLink(*dobj);
192 //since dobj is identifiable in the SG a reference to it is all we need
193
195 dobj2 = std::make_unique<MyDataObj> (2);
196
197 //Otherwise one could first create an empty link
198 DataLink<MyDataObj> dobjLink2;
199 //and later on set it to refer to its target
200 dobjLink2.toStorableObject(*dobj2);
201
202
203 // Added Aug 30, 2001 HMA
204 // DataLink made from a key. This should work for either an object
205 // already registered in the store, or an object that has a
206 // persistency for it. we use dobj3, which is an object registered with
207 // a key.
208
209 DataLink<MyDataObj> dobjLink3(name());
210 // now access it. DataLink will do a retrieve to get it from the store.
211 (void)dobjLink3.cptr();
212
213 //
214 // ElementLinks referring to contained objects
215 //
216 typedef ElementLink<std::vector<float> > VecElemLink;
217
218
219 VecElemLink thirdElementLink(*vFloat, 2); //THIS CRASHES SUN CC
220
221 //sometimes we would not know the index of the element we want to refer to
222
223 //reference to an element of the vector
224 float& anElement = vFloat->operator[](0);
225
226 //starting from an empty link
227 VecElemLink aLink;
228 //we can refer it to its target without knowing its index
229 aLink.toContainedElement(*vFloat, anElement);
230 //it is better though to remember that toContainedElement for an
231 //ElementLink performs a linear search of "anElement" into "vFloat".
232 // If vFloat has a million elements think twice before using
233 // toContainedElement!
234
236 pLinkList = std::make_unique<std::list<VecElemLink> >();
237 pLinkList->push_back(aLink);
238 pLinkList->push_back(thirdElementLink);
239
240 //
241 // Part 3b: create a vector of links to the elements of the map above
242 //
243 typedef ElementLink<MapStringFloat> MapElemLink;
245 linkVector = std::make_unique<std::vector<MapElemLink> >();
246 linkVector->push_back(MapElemLink(*m, "uno"));
247 MapElemLink mLink;
248 mLink.toContainedElement(*m, (*m)["due"]);
249 linkVector->push_back(mLink);
250
251 // Part 4
252 // make a link to dobj as its base class after it has been registered
253 // this allows later to retrieve different concrete types as a common ABC
254
255 const BaseClass * pDO = 0;
256 if ( (evtStore()->symLink(dobj.cptr(), pDO)).isFailure() ) {
257 ATH_MSG_ERROR (" could not make link to BaseClass");
258 return( onError() );
259 }
260
261 // make a link as its base class, with the same name
262 if ( ( evtStore()->symLink(dobj3.cptr(), pDO)).isFailure() ) {
263 ATH_MSG_ERROR (" could not make link to BaseClass");
264 return( onError() );
265 }
266
267 // Part 5
268 // finally dump the structure of the StoreGate before returning
269 ATH_MSG_INFO (" registered all data objects");
270 ATH_MSG_INFO (" StoreGate structure before returning from execute \n"
271 << evtStore()->dump());
272
273 return StatusCode::SUCCESS;
274}
275
276// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
277
279{
280 ATH_MSG_ERROR ("Dumping StoreGate after error occurred\n"
281 << evtStore()->dump());
282 return StatusCode::FAILURE;
283}
284
#define ATH_CHECK
Evaluate an expression and check for errors.
#define ATH_MSG_ERROR(x)
#define ATH_MSG_INFO(x)
#define ATH_MSG_WARNING(x)
Helpers for checking error return status codes and reporting errors.
An STL vector of pointers that by default owns its pointed-to elements.
Handle class for recording to StoreGate.
Testing reentrant algorithms.
Header file for AthHistogramAlgorithm.
Derived DataVector<T>.
Definition DataVector.h:795
Property holding a SG store/key/clid from which a WriteHandle is made.
const_pointer_type cptr() const
Dereference the pointer.
StatusCode record(std::unique_ptr< T > data)
Record a const object to the store.
virtual StatusCode execute(const EventContext &ctx) const override final
SG::WriteHandleKey< DataVector< MyContObj > > m_cobjKey
SG::WriteHandleKeyArray< MyDataObj > m_dobjKeyArray
SG::WriteHandleKey< std::vector< ElementLink< MapStringFloat > > > m_linkVectorKey
SG::WriteHandleKey< std::vector< float > > m_vFloatKey
SG::WriteHandleKey< TestDataObject > m_testObjectKey
SG::WriteHandleKey< std::list< ElementLink< std::vector< float > > > > m_pLinkListKey
SG::DataObjectSharedPtr< TestDataObject > m_testObject
SG::WriteHandleKey< MyDataObj > m_dobjKey2
virtual StatusCode initialize() override final
SG::WriteHandleKey< MyDataObj > m_dobjKey3
SG::WriteHandleKey< MyDataObj > m_dobjKey
StatusCode onError() const
SG::WriteHandleKey< MapStringFloat > m_mKey
static void hideErrorLocus(bool flag=true)
If set to true, hide the source file and line number in the output.
Helper to check that an exception is thrown.
#define EXPECT_EXCEPTION(EXC, CODE)
Helper to check that an exception is thrown.
CxxUtils::RefCountedPtr< T > DataObjectSharedPtr
SG::ReadCondHandle< T > makeHandle(const SG::ReadCondHandleKey< T > &key, const EventContext &ctx=Gaudi::Hive::currentContext())
-event-from-file