ATLAS Offline Software
Loading...
Searching...
No Matches
DVLDataBucket.icc
Go to the documentation of this file.
1// This file's extension implies that it's C, but it's really -*- C++ -*-.
2
3/*
4 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5*/
6/**
7 * @file AthContainers/tools/DVLDataBucket.icc
8 * @author scott snyder
9 * @date Mar 2008
10 * @brief A @c DataBucket specialized for @c DataVector/@c DataList.
11 *
12 * Template and inline implementations.
13 */
14
15
16#include "AthContainers/exceptions.h"
17#include "AthenaKernel/IRegisterTransient.h"
18#include "CxxUtils/AthUnlikelyMacros.h"
19
20
21namespace SG {
22
23
24/**
25 * @brief Is a @c DataVector we're trying to record actually a @c ViewVector?
26 * @param data Object being recorded.
27 * @param[out] clid If the object is a @c ViewVector, set to the CLID
28 * of that class. Otherwise unchanged.
29 * @returns The @c type_info for the object being recorded, either the
30 * @c DataVector or a @c ViewVector that derives from it.
31 */
32template <class T>
33const std::type_info* testViewVector (const DataVector<T>& data,
34 CLID& clid)
35{
36 // If this is a view container, test for @c ViewVector.
37 if (data.ownPolicy() == SG::VIEW_ELEMENTS) {
38 // See if we actually have a @c ViewVector.
39 // FIXME: This doesn't work if @c ViewVector is templated on an intermediate
40 // class rather than @c DataVector directly.
41 if (dynamic_cast<const ViewVector<DataVector<T> >*> (&data)) {
42 const std::type_info& ti = typeid(ViewVector<DataVector<T> >);
43 const SG::BaseInfoBase* bib = SG::BaseInfoBase::find (ti);
44 if (bib) {
45 clid = bib->clid();
46 if (clid == CLID_NULL)
47 SG::throwExcMissingViewVectorCLID (ti);
48 return &ti;
49 }
50 else {
51 SG::throwExcMissingBaseInfo (ti);
52 }
53 }
54 }
55 return &typeid(DataVector<T>);
56}
57
58
59/**
60 * @brief Is a @c DataVector we're trying to record actually a @c ViewVector?
61 *
62 * Handle the case where the object being recorded is not a @c DataVector.
63 */
64template <class T>
65const std::type_info* testViewVector (const T& ,
66 CLID& )
67{
68 return &typeid(T);
69}
70
71
72/**
73 * @brief Constructor from a payload object.
74 * @param data Object to hold in the bucket.
75 */
76template <class T>
77DVLDataBucket<T>::DVLDataBucket (T* data)
78 : DataBucket<T> (data)
79{
80 // cppcheck-suppress useInitializationList
81 m_clid = DataBucket<T>::classID();
82 m_ti = testViewVector (*this->ptr(), m_clid);
83}
84
85
86/**
87 * @brief Constructor from a payload object.
88 * @param data Object to hold in the bucket.
89 */
90template <class T>
91template <class U>
92DVLDataBucket<T>::DVLDataBucket (std::unique_ptr<U> data)
93 : DataBucket<T> (std::move (data))
94{
95 // cppcheck-suppress useInitializationList
96 m_clid = DataBucket<T>::classID();
97 // cppcheck-suppress missingReturn; false positive
98 m_ti = testViewVector (*this->ptr(), m_clid);
99}
100
101
102/**
103 * @brief Copy constructor.
104 * @param other Bucket to copy.
105 */
106template <typename T>
107DVLDataBucket<T>::DVLDataBucket (const DVLDataBucket& other)
108 : SG::DataBucket<T> (new T (*other.cptr())),
109 m_copies (other.m_copies),
110 m_ti (other.m_ti),
111 m_clid (other.m_clid)
112{
113 // Make a copy of each of the copies.
114 vec_t::iterator end = m_copies.end();
115 for (vec_t::iterator it = m_copies.begin(); it != end; ++it) {
116 it->second = it->first->clone (it->second);
117 }
118}
119
120
121/**
122 * @brief Destructor.
123 */
124template <typename T>
125DVLDataBucket<T>::~DVLDataBucket()
126{
127 // Delete any copies.
128 vec_t::iterator end = m_copies.end();
129 for (vec_t::iterator it = m_copies.begin(); it != end; ++it) {
130 it->first->del (it->second);
131 }
132}
133
134
135/**
136 * @brief Return the contents of the @c DataBucket,
137 * converted to type given by @a clid. Note that only
138 * derived->base conversions are allowed here.
139 * @param clid The class ID to which to convert.
140 * @param irt To be called if we make a new instance.
141 * @param isConst True if the object being converted is regarded as const.
142 */
143template <typename T>
144void*
145DVLDataBucket<T>::cast (CLID clid, IRegisterTransient* irt /*= 0*/,
146 bool /*isConst = true*/)
147{
148 // Test for trivial conversion.
149 // FIXME: Assumes we can reinterpret_cast between DV* and ViewVector<DV>*.
150 if (ATH_LIKELY (clid == m_clid) || clid == DataBucket<T>::classID())
151 return this->ptr();
152
153 // Try looking for a true base conversion,
154 // first using static SG_BASES information.
155 // This can all be unfolded at compile time, so is fast, but
156 // doesn't take into account SG_ADD_BASES.
157 void* ret = this->tryStaticConversion (clid);
158 if (ret) {
159 return ret;
160 }
161
162 T* ptr = this->ptr();
163
164 // Then try using BaseInfo, in case of SG_ADD_BASES.
165 ret = SG::BaseInfo<T>::cast (ptr, clid);
166 if (ret) {
167 return ret;
168 }
169
170 // See if we've already made an instance for this type.
171 // We don't expect to have more than a few, so no point in doing
172 // anything more complicated than a linear search.
173 vec_t::iterator end = m_copies.end();
174 for (vec_t::iterator it = m_copies.begin(); it != end; ++it) {
175 if (clid == it->first->clid()) {
176 // Recopy the elements if the container size has changed.
177 if (it->first->size (it->second) != ptr->size()) {
178 dvl_update (*ptr, it->second, it->first);
179 }
180 return it->second;
181 }
182 }
183
184 // Try to do a copying conversion.
185 DataModel_detail::DVLInfoBase* info;
186 void* newcont = dvl_convert (*ptr, clid, info);
187 if (newcont) {
188 m_copies.push_back (std::make_pair (info, newcont));
189 irt->registerTransient (newcont);
190 }
191
192 return newcont;
193}
194
195
196/**
197 * @brief Return the contents of the @c DataBucket,
198 * converted to type given by @a std::type_info. Note that only
199 * derived->base conversions are allowed here.
200 * @param clid The @a std::type_info of the type to which to convert.
201 * @param irt To be called if we make a new instance.
202 * @param isConst True if the object being converted is regarded as const.
203 */
204template <typename T>
205void*
206DVLDataBucket<T>::cast (const std::type_info& tinfo,
207 IRegisterTransient* irt /*= 0*/,
208 bool /*isConst = true*/)
209{
210 // Test for trivial conversion.
211 // FIXME: Assumes we can reinterpret_cast between DV* and ViewVector<DV>*.
212 if (ATH_LIKELY (&tinfo == m_ti) || tinfo == DataBucket<T>::tinfo())
213 return this->ptr();
214
215 // Try looking for a true base conversion,
216 // first using static SG_BASES information.
217 // This can all be unfolded at compile time, so is fast, but
218 // doesn't take into account SG_ADD_BASES.
219 void* ret = this->tryStaticConversion (tinfo);
220 if (ret) {
221 return ret;
222 }
223
224 T* ptr = this->ptr();
225
226 // Try looking for a true base conversion.
227 ret = SG::BaseInfo<T>::cast (ptr, tinfo);
228 if (ret) {
229 return ret;
230 }
231
232 // See if we've already made an instance for this type.
233 // We don't expect to have more than a few, so no point in doing
234 // anything more complicated than a linear search.
235 vec_t::iterator end = m_copies.end();
236 for (vec_t::iterator it = m_copies.begin(); it != end; ++it) {
237 if (tinfo == it->first->tinfo()) {
238 // Recopy the elements if the container size has changed.
239 if (it->first->size (it->second) != ptr->size()) {
240 dvl_update (*ptr, it->second, it->first);
241 }
242 return it->second;
243 }
244 }
245
246 // Try to do a copying conversion.
247 DataModel_detail::DVLInfoBase* info;
248 void* newcont = dvl_convert (*ptr, tinfo, info);
249 if (newcont) {
250 m_copies.push_back (std::make_pair (info, newcont));
251 irt->registerTransient (newcont);
252 }
253
254 return newcont;
255}
256
257
258/**
259 * @brief Return the contents of the @c DataBucket,
260 * converted to type given by @a clid. Note that only
261 * derived->base conversions are allowed here.
262 * @param clid The class ID to which to convert.
263 * @param tinfo The @a std::type_info of the type to which to convert.
264 * @param irt To be called if we make a new instance.
265 * @param isConst True if the object being converted is regarded as const.
266 *
267 * This allows the callee to choose whether to use clid or tinfo.
268 * Here we use clid.
269 */
270template <typename T>
271inline
272void* DVLDataBucket<T>::cast (CLID clid,
273 const std::type_info& /*tinfo*/,
274 SG::IRegisterTransient* irt /*= 0*/,
275 bool isConst /*= true*/)
276{
277 return DVLDataBucket::cast (clid, irt, isConst);
278}
279
280
281/**
282 * @brief The CLID for the class of object we're holding.
283 *
284 * May be different from that of the base @c DataVector in the case
285 * of a @c ViewVector.
286 */
287template <typename T>
288const CLID& DVLDataBucket<T>::clID() const
289{
290 return m_clid;
291}
292
293
294/**
295 * @brief The std::type_info for the class of object we're holding.
296 *
297 * May be different from that of the base @c DataVector in the case
298 * of a @c ViewVector.
299 */
300template <typename T>
301const std::type_info& DVLDataBucket<T>::tinfo() const
302{
303 return *m_ti;
304}
305
306
307} // namespace SG