ATLAS Offline Software
Loading...
Searching...
No Matches
SystematicsHandles/SystematicsHandles/CopyHelpers.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3*/
4
6
7
8#ifndef SYSTEMATICS_HANDLES__COPY_HELPERS_H
9#define SYSTEMATICS_HANDLES__COPY_HELPERS_H
10
21
22#include <memory>
23#include <type_traits>
24#include <utility> //std::declval
25
26namespace CP
27{
28 namespace detail
29 {
31 template <typename T>
33 {
34 template <class, class> class checker;
35
36 template <typename C>
37 static std::true_type test_iparticle(checker<C, decltype((*(const xAOD::IParticle**)nullptr) = ((C*)nullptr)->at(0))> *);
38
39 template <typename C>
40 static std::false_type test_iparticle(...);
41
42 template <typename C>
43 static std::true_type test_container(checker<C, decltype((*(const SG::AuxVectorBase**)nullptr) = ((C*)nullptr))>*);
44
45 template <typename C>
46 static std::false_type test_container(...);
47
52 static const int value = ( std::is_same< std::true_type, decltype( test_iparticle< T >( nullptr ) ) >::value ?
53 1 : ( std::is_same< std::true_type, decltype( test_container< T >( nullptr ) ) >::value ?
54 2 : 3 ) );
55 };
56
64 template<typename T, int type = ContainerType<T>::value>
66 {
67 static_assert ((type==1)||(type==2)||(type==3),
68 "Type can not be shallow copied");
69 };
70
71 template<typename T>
72 struct ShallowCopy<T,1>
73 {
74 static StatusCode
75 getCopy (MsgStream& msgStream, const EventContext& ctx,
76 T*& object, const T *inputObject,
77 const std::string& outputName)
78 {
79 // Define the msg(...) function as a lambda.
80 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
81 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
82 msgStream << lvl;
83 return msgStream;
84 };
85
86 // Make sure that we get a valid pointer.
87 assert (inputObject != nullptr);
88
89 // Handle the case when the input object is a view container.
90 if( ! inputObject->getConstStore() ) {
91
92 // Decide how to handle the container.
93 if( inputObject->size() ) {
94 // Get the pointer to the "owning container" from the first
95 // element.
96 const T* originContainer =
97 dynamic_cast< const T* >( ( *inputObject )[ 0 ]->container() );
98 if (!originContainer){
99 ANA_MSG_ERROR( "Dynamic cast failed." );
100 return StatusCode::FAILURE;
101 }
102 // Make sure that every element in the view container has the same
103 // parent.
104 for( size_t i = 1; i < inputObject->size(); ++i ) {
105 if( ( *inputObject )[ i ]->container() != originContainer ) {
106 ANA_MSG_ERROR( "Not all elements of the received view "
107 "container come from the same container!" );
108 return StatusCode::FAILURE;
109 }
110 }
111 // Postfix for the shallow-copy container of the origin container.
112 static const char* const ORIGIN_POSTFIX = "_ShallowCopyOrigin";
113 // Make a shallow copy of the origin container.
114 auto originCopy = xAOD::shallowCopy( *originContainer );
115 if( ( ! originCopy.first ) || ( ! originCopy.second ) ) {
116 ANA_MSG_ERROR( "Failed to shallow copy the origin of a view "
117 << "container, meant for: " << outputName );
118 return StatusCode::FAILURE;
119 }
120 // Make a view copy on top of it.
121 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
122 auto viewCopyPtr = viewCopy.get();
123 for( const auto* element : *inputObject ) {
124 viewCopy->push_back( originCopy.first->at( element->index() ) );
125 }
126
127 // ...and record it without locking, since the caller will
128 // typically still modify the copy.
129 SG::WriteHandle<T> originHandle( outputName + ORIGIN_POSTFIX, ctx );
130 ANA_CHECK( originHandle.recordNonConst( std::move(originCopy.first),
131 std::move(originCopy.second) ) );
132
133 // Set the origin links on it. Note that
134 // xAOD::setOriginalObjectLink's "container version" doesn't work
135 // with view containers, we have to call this function one-by-one
136 // on the elements.
137 for( size_t i = 0; i < inputObject->size(); ++i ) {
138 if( ! xAOD::setOriginalObjectLink( *( ( *inputObject )[ i ] ),
139 *( ( *viewCopy )[ i ] ) ) ) {
140 return StatusCode::FAILURE;
141 }
142 }
143 // Finally, record the view container with the requested name.
144 SG::WriteHandle<T> viewHandle( outputName, ctx );
145 ANA_CHECK( viewHandle.recordNonConst( std::move(viewCopy) ) );
146 // The copy is done.
147 object = viewCopyPtr;
148 return StatusCode::SUCCESS;
149 } else {
150 // If the container was empty, then let's just make a new empty
151 // container, and that's that...
152 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
153 auto viewCopyPtr = viewCopy.get();
154 SG::WriteHandle<T> viewHandle( outputName, ctx );
155 ANA_CHECK( viewHandle.recordNonConst( std::move(viewCopy) ) );
156 // The copy is done.
157 object = viewCopyPtr;
158 return StatusCode::SUCCESS;
159 }
160
161 } else {
162
163 // We can just copy the container as is.
164 auto copy = xAOD::shallowCopy( *inputObject );
165 if (!copy.first || !copy.second)
166 {
167 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
168 ANA_MSG_ERROR ("likely shallow copying a view container");
169 return StatusCode::FAILURE;
170 }
171
172 if (!xAOD::setOriginalObjectLink (*inputObject, *copy.first)) {
173 return StatusCode::FAILURE;
174 }
175 //coverity[WRAPPER_ESCAPE]
176 object = copy.first.get();
177 // Record the copy and its aux store without locking, since the
178 // caller will typically still modify it.
179 SG::WriteHandle<T> handle (outputName, ctx);
180 ANA_CHECK (handle.recordNonConst (std::move(copy.first), std::move(copy.second)));
181 return StatusCode::SUCCESS;
182 }
183 }
184 };
185
186 template<typename T>
187 struct ShallowCopy<T,2>
188 {
189 static StatusCode
190 getCopy (MsgStream& msgStream, const EventContext& ctx,
191 T*& object, const T *inputObject,
192 const std::string& outputName)
193 {
194 // Define the msg(...) function as a lambda.
195 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
196 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
197 msgStream << lvl;
198 return msgStream;
199 };
200
201 // Make sure that we get a valid pointer.
202 assert (inputObject != nullptr);
203
204 // Handle the case when the input object is a view container.
205 if( ! inputObject->getConstStore() ) {
206
207 // Decide how to handle the container.
208 if( inputObject->size() ) {
209 // Get the pointer to the "owning container" from the first
210 // element.
211 const T* originContainer = dynamic_cast< const T* >( ( *inputObject )[ 0 ]->container() );
212 if (!originContainer){
213 ANA_MSG_ERROR( "Dynamic cast returned nullptr!" );
214 return StatusCode::FAILURE;
215 }
216 // Make sure that every element in the view container has the same
217 // parent.
218 for( size_t i = 1; i < inputObject->size(); ++i ) {
219 if( ( *inputObject )[ i ]->container() != originContainer ) {
220 ANA_MSG_ERROR( "Not all elements of the received view "
221 "container come from the same container!" );
222 return StatusCode::FAILURE;
223 }
224 }
225 // Postfix for the shallow-copy container of the origin container.
226 static const char* const ORIGIN_POSTFIX = "_ShallowCopyOrigin";
227 // Make a shallow copy of the origin container.
228 auto originCopy = xAOD::shallowCopy( *originContainer );
229 if( ( ! originCopy.first ) || ( ! originCopy.second ) ) {
230 ANA_MSG_ERROR( "Failed to shallow copy the origin of a view "
231 << "container, meant for: " << outputName );
232 return StatusCode::FAILURE;
233 }
234
235 // Make a view copy on top of it.
236 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
237 auto viewCopyPtr = viewCopy.get();
238 for( const auto* element : *inputObject ) {
239 viewCopy->push_back( originCopy.first->at( element->index() ) );
240 }
241
242 // ...and record it without locking, since the caller will
243 // typically still modify the copy.
244 SG::WriteHandle<T> originHandle( outputName + ORIGIN_POSTFIX, ctx );
245 ANA_CHECK( originHandle.recordNonConst( std::move(originCopy.first),
246 std::move(originCopy.second) ) );
247
248 // Finally, record the view container with the requested name.
249 SG::WriteHandle<T> viewHandle( outputName, ctx );
250 ANA_CHECK( viewHandle.recordNonConst( std::move(viewCopy) ) );
251 // The copy is done.
252 object = viewCopyPtr;
253 return StatusCode::SUCCESS;
254 } else {
255 // If the container was empty, then let's just make a new empty
256 // container, and that's that...
257 auto viewCopy = std::make_unique< T >( SG::VIEW_ELEMENTS );
258 auto viewCopyPtr = viewCopy.get();
259 SG::WriteHandle<T> viewHandle( outputName, ctx );
260 ANA_CHECK( viewHandle.recordNonConst( std::move(viewCopy) ) );
261 // The copy is done.
262 object = viewCopyPtr;
263 return StatusCode::SUCCESS;
264 }
265
266 } else {
267
268 // We can just copy the container as is.
269 auto copy = xAOD::shallowCopy( *inputObject );
270 if (!copy.first || !copy.second)
271 {
272 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
273 ANA_MSG_ERROR ("likely shallow copying a view container");
274 return StatusCode::FAILURE;
275 }
276 //coverity warns about the bare pointer outliving the 'copy' object
277 //coverity[WRAPPER_ESCAPE]
278 object = copy.first.get();
279 // Record the copy and its aux store without locking, since the
280 // caller will typically still modify it.
281 SG::WriteHandle<T> handle (outputName, ctx);
282 ANA_CHECK (handle.recordNonConst (std::move(copy.first), std::move(copy.second)));
283 return StatusCode::SUCCESS;
284 }
285 }
286 };
287
288 template<typename T>
289 struct ShallowCopy<T,3>
290 {
291 static StatusCode
292 getCopy (MsgStream& msgStream, const EventContext& ctx,
293 T*& object, const T *inputObject,
294 const std::string& outputName)
295 {
296 // Define the msg(...) function as a lambda.
297 // Suppress thread-checker warning because this provides just a wrapper to MsgStream.
298 const auto msg = [&] ATLAS_NOT_THREAD_SAFE (MSG::Level lvl) -> MsgStream& {
299 msgStream << lvl;
300 return msgStream;
301 };
302
303 // We can just copy the object as is.
304 auto copy = xAOD::shallowCopy( *inputObject );
305 if (!copy.first || !copy.second)
306 {
307 ANA_MSG_ERROR ("failed to shallow copy object: " << outputName);
308 ANA_MSG_ERROR ("likely shallow copying a view container");
309 return StatusCode::FAILURE;
310 }
311 //coverity[WRAPPER_ESCAPE]
312 object = copy.first.get();
313 // Record the copy and its aux store without locking, since the
314 // caller will typically still modify it.
315 SG::WriteHandle<T> handle (outputName, ctx);
316 ANA_CHECK (handle.recordNonConst (std::move(copy.first), std::move(copy.second)));
317 return StatusCode::SUCCESS;
318 }
319 };
320
321 template<>
323 {
324 static StatusCode
325 getCopy (MsgStream& msgStream, const EventContext& ctx,
327 const xAOD::IParticleContainer *inputObject,
328 const std::string& outputName);
329 };
330 }
331}
332
333#endif
Handle class for recording to StoreGate.
macros for messaging and checking status codes
#define ANA_MSG_ERROR(xmsg)
Macro printing error messages.
#define ANA_CHECK(EXP)
check whether the given expression was successful
Define macros for attributes used to control the static checker.
Manage index tracking and synchronization of auxiliary data.
StatusCode recordNonConst(std::unique_ptr< T > data)
Record a non-const object to the store.
Class providing the definition of the 4-vector interface.
struct color C
Select isolated Photons, Electrons and Muons.
@ VIEW_ELEMENTS
this data object is a view, it does not own its elmts
STL namespace.
ICaloAffectedTool is abstract interface for tools checking if 4 mom is in calo affected region.
ShallowCopyResult_t< T > shallowCopy(const T &cont, const EventContext &ctx)
Create a shallow copy of an existing container.
bool setOriginalObjectLink(const IParticle &original, IParticle &copy)
This function should be used by CP tools when they make a deep copy of an object in their correctedCo...
void ClearTransientTrees ATLAS_NOT_THREAD_SAFE()
Function cleaning up the managed memory.
DataVector< IParticle > IParticleContainer
Simple convenience declaration of IParticleContainer.
check what kind of object/container the argument is
static std::true_type test_container(checker< C, decltype((*(const SG::AuxVectorBase **) nullptr)=((C *) nullptr))> *)
static std::false_type test_iparticle(...)
static std::false_type test_container(...)
static std::true_type test_iparticle(checker< C, decltype((*(const xAOD::IParticle **) nullptr)=((C *) nullptr) ->at(0))> *)
static StatusCode getCopy(MsgStream &msgStream, const EventContext &ctx, T *&object, const T *inputObject, const std::string &outputName)
static StatusCode getCopy(MsgStream &msgStream, const EventContext &ctx, T *&object, const T *inputObject, const std::string &outputName)
static StatusCode getCopy(MsgStream &msgStream, const EventContext &ctx, T *&object, const T *inputObject, const std::string &outputName)
static StatusCode getCopy(MsgStream &msgStream, const EventContext &ctx, xAOD::IParticleContainer *&object, const xAOD::IParticleContainer *inputObject, const std::string &outputName)
a helper class to create shallow copies and register them in the event store
MsgStream & msg
Definition testRead.cxx:32