ATLAS Offline Software
ViewVectorBase.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 // $Id$
6 /**
7  * @file ViewVectorBase.icc
8  * @author scott snyder <snyder@bnl.gov>
9  * @date Sep, 2016
10  * @brief Hold the persistent representation for a ViewVector.
11  */
12 
13 
14 #include "AthContainers/AuxElement.h"
15 #include "CxxUtils/checker_macros.h"
16 #include <type_traits>
17 
18 
19 namespace {
20 
21 
22 template <class T>
23 inline
24 SG::AuxVectorData* getContainer1 (T* p, const std::true_type&)
25 {
26  return p->container();
27 }
28 template <class T>
29 inline
30 SG::AuxVectorData* getContainer1 (T*, const std::false_type&)
31 {
32  return nullptr;
33 }
34 
35 
36 /**
37  * @brief Return the container for an element.
38  *
39  * Returns null if the element does not derive from AuxElement.
40  */
41 template <class T>
42 inline
43 SG::AuxVectorData* getContainer (T* p)
44 {
45  return getContainer1 (p, typename std::is_base_of<SG::AuxElement, T>::type());
46 }
47 
48 
49 } // anonymous namespace
50 
51 
52 namespace SG {
53 
54 
55 /**
56  * @brief Clear the persistent data.
57  */
58 inline
59 void ViewVectorBase::clearPersistent()
60 {
61  m_persKey.clear();
62  m_persIndex.clear();
63 }
64 
65 
66 /**
67  * @brief Set a flag to declare that the vector should be cleared
68  * on the next call to toPersistent().
69  *
70  * This would be used in the case where we make a copy of the
71  * object being written.
72  */
73 inline
74 void ViewVectorBase::setClearOnPersistent()
75 {
76  m_clearOnPersistent = true;
77 }
78 
79 
80 /**
81  * @brief Convert to persistent form.
82  * @param v The vector to convert.
83  *
84  * Called for classes that have a CLID.
85  */
86 template <class DV>
87 void
88 ViewVectorBase::doToPersistent1 (DV& v, const std::true_type&)
89 {
90  IProxyDict* store = SG::CurrentEventStore::store();
91  std::vector<ElementLink<DV> > elv = SG::dataVectorAsELV (v, store);
92  m_persKey.clear();
93  m_persIndex.clear();
94  m_persKey.reserve (elv.size());
95  m_persIndex.reserve (elv.size());
96  for (ElementLinkBase& el : elv) {
97 #ifdef XAOD_STANDALONE
98  m_persKey.push_back (el.persKey());
99  m_persIndex.push_back (el.persIndex());
100 #else
101  el.thin();
102  m_persKey.push_back (el.key());
103  m_persIndex.push_back (el.index());
104 #endif
105  }
106  if (m_clearOnPersistent) {
107  v.clear();
108  m_clearOnPersistent = false;
109  }
110 }
111 
112 
113 /**
114  * @brief Convert to persistent form.
115  * @param v The vector to convert.
116  *
117  * Called for classes that do not have a CLID.
118  * This will simply abort.
119  */
120 template <class DV>
121 inline
122 void ViewVectorBase::doToPersistent1 (DV&, const std::false_type&)
123 {
124  std::abort();
125 }
126 
127 
128 /**
129  * @brief Convert to persistent form.
130  * @param v The vector to convert.
131  *
132  * This will abort if called for a class with no CLID.
133  */
134 template <class DV>
135 inline
136 void ViewVectorBase::doToPersistent (DV& v)
137 {
138  // Dispatch depending on whether or not DV has a CLID.
139  doToPersistent1 (v,
140 #ifdef XAOD_STANDALONE
141  std::true_type()
142 #else
143  typename ClassID_traits<DV>::has_classID_tag()
144 #endif
145  );
146 }
147 
148 
149 /**
150  * @brief Convert to transient form.
151  * @param v The vector to fill in.
152  *
153  * Called for classes that have a CLID if DV is not a ConstDataVector.
154  */
155 template <class DV>
156 void ViewVectorBase::doToTransient2 (DV& v, const std::true_type&)
157 {
158  // The custom DataVector collection proxy will have created elements here,
159  // so we need to delete them to avoid a memory leak.
160  // FIXME: It should be possible to avoid creating the elements
161  // in the first place, at least for the usual case xAOD where the elements
162  // themselves have no persistent data.
163  if (v.ownPolicy() == SG::VIEW_ELEMENTS) {
164  for (typename DV::value_type p : v) {
165  // Try to protect against deleting an unowned object in the case
166  // where this gets called multiple times on the same object.
167  // The dummy elements will have null container pointers, while
168  // those that we've retrieved through EL resolution below should
169  // have the container pointer set. Can only do this check, though,
170  // for types with aux data.
171  if (getContainer(p) == nullptr)
172  delete p;
173  }
174  }
175  v.clear (SG::VIEW_ELEMENTS);
176  IProxyDict* store = SG::CurrentEventStore::store();
177 
178  assert (m_persKey.size() == m_persIndex.size());
179  for (size_t i = 0; i < m_persKey.size(); i++) {
180  ElementLink<DV> el (m_persKey[i], m_persIndex[i], store);
181  // FIXME: const_cast
182  typename DV::value_type p ATLAS_THREAD_SAFE = const_cast<typename DV::value_type> (*el);
183  v.push_back (p);
184  }
185 }
186 
187 
188 } // namespace SG
189 
190