ATLAS Offline Software
AthLinks/ElementLinkVector.icc
Go to the documentation of this file.
1 // Dear emacs, this is -*- c++ -*-
2 
3 /*
4  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
5 */
6 
7 #include "GaudiKernel/System.h"
8 #include "AthenaKernel/errorcheck.h"
9 
10 #include <cassert>
11 #include <stdexcept>
12 /* #define __ELVDEBUG */
13 
14 template <typename DOBJ>
15 typename ElementLinkVector<DOBJ>::DataLinkVector::const_iterator
16 ElementLinkVector<DOBJ>::findHostDObj(const ElemLink& link) const
17 {
18  //DataLink<DOBJ> dl (link.storagePolicy());
19  DataLink<DOBJ> dl = link.getDataLink();
20  typename DataLinkVector::const_iterator iHost(beginHostDObjs()), eHost(endHostDObjs());
21  while ((eHost != iHost) && (*iHost != dl)) ++iHost;
22 #ifdef __ELVDEBUG
23  std::cout << "findHostDObj (const version) called for link "
24  << link.dataID() << "/" << link.index()
25  << " - which is " << ((iHost != eHost) ? "" : " NOT ")
26  << " in ELV host dobjs list " << std::endl;
27 #endif
28  return iHost;
29 }
30 
31 template <typename DOBJ>
32 typename ElementLinkVector<DOBJ>::DataLinkVector::iterator
33 ElementLinkVector<DOBJ>::findHostDObj(const ElemLink& link)
34 {
35  //DataLink<DOBJ> dl (link.storagePolicy());
36  DataLink<DOBJ> dl (link.key());
37  typename DataLinkVector::iterator iHost(beginHostDObjs()), eHost(endHostDObjs());
38  while ((eHost != iHost) && (*iHost != dl)) ++iHost;
39 #ifdef __ELVDEBUG
40  std::cout << "findHostDObj (non-const version) called for link "
41  << link.dataID() << "/" << link.index()
42  << " - which is " << ((iHost != eHost) ? "" : " NOT ")
43  << " in ELV host dobjs list " << std::endl;
44 #endif
45  return iHost;
46 }
47 
48 
49 template <typename DOBJ>
50 typename ElementLinkVector<DOBJ>::iterator
51 ElementLinkVector<DOBJ>::insert(iterator position, const ElemLink& link)
52 {
53 #ifdef __ELVDEBUG
54  std::cout << "insert of link "
55  << link.dataID() << "/" << link.index() << " after "
56  << position->dataID() << "/" << position->index() <<endl;
57 #endif
58  addHostDObj(link);
59  return iterator(m_shortRefs.insert(shortIterFromLong(position), ElemLinkRef( link)),
60  Short2LongRef());
61 }
62 
63 template <typename DOBJ>
64 void
65 ElementLinkVector<DOBJ>::insert(iterator position, size_type n, const ElemLink& link)
66 {
67  addHostDObj(link);
68  m_shortRefs.insert(shortIterFromLong(position), n, ElemLinkRef(link));
69 }
70 
71 template <typename DOBJ>
72 typename ElementLinkVector<DOBJ>::iterator
73 ElementLinkVector<DOBJ>::erase(iterator position)
74 {
75  const ElemLink& save(*position);
76  iterator ret(m_shortRefs.erase(shortIterFromLong(position)), Short2LongRef());
77  removeHostObj(save);
78  return ret;
79 }
80 
81 template <typename DOBJ>
82 typename ElementLinkVector<DOBJ>::iterator
83 ElementLinkVector<DOBJ>::erase(iterator first, iterator last)
84 {
85  iterator i(first);
86  while (i != last) removeHostObj(*i++); //FIXME won't work in ELVDEBUG as such
87  return iterator(m_shortRefs.erase(shortIterFromLong(first),
88  shortIterFromLong(last)),
89  Short2LongRef());
90 }
91 
92 template <typename DOBJ>
93 void
94 ElementLinkVector<DOBJ>::
95 resize(size_type sz, const ElemLink& link)
96 {
97  if (sz > size()) { insert(end(), sz-size(), link); }
98  else if (sz < size()) { erase(begin()+sz, end()); }
99 }
100 
101 template <typename DOBJ>
102 bool
103 ElementLinkVector<DOBJ>::toTransient()
104 {
105  // Call the appropriate function for making use of the persistent data
106  // if we're doing direct ROOT I/O:
107  if( m_isDirectIO ) {
108  index_type dummy;
109  toTransient( dummy );
110  m_isDirectIO = false;
111  }
112 
113  bool success = true;
114  // set the proper state of all DataLinks
115  typename DataLinkVector::iterator iter = beginHostDObjs();
116  for (; iter!= endHostDObjs(); ++iter) {
117  if (! (*iter).toTransient()) success = false;
118  }
119 
120  // set the refVector's to transient mode. Note that RefVector would
121  // need the owner (this) as it is constructed from persistency using
122  // the default constructor
123  typename RefVector::iterator refIter = m_shortRefs.begin();
124  for (; refIter!= m_shortRefs.end(); ++refIter) {
125  if (! (*refIter).toTransient(*this)) success = false;
126  }
127 
128  return success;
129 }
130 
131 
132 template <typename DOBJ>
133 bool
134 ElementLinkVector<DOBJ>::toPersistentDL()
135 {
136  doRemap();
137 
138  //set all DataLinks to persistent state
139  bool success = true;
140  typename DataLinkVector::iterator iter = beginHostDObjs();
141  for (; iter!= endHostDObjs(); ++iter) {
142  if (! (*iter).toPersistentNoRemap()) success = false;
143  }
144 
145  return success;
146 }
147 
148 
149 template <typename DOBJ>
150 bool
151 ElementLinkVector<DOBJ>::toPersistent()
152 {
153  bool success = toPersistentDL();
154 
155  // set all ElementLink Refs to persistent state
156  typename RefVector::iterator refIter = m_shortRefs.begin();
157  for (; refIter!= m_shortRefs.end(); ++refIter) {
158  if (! (*refIter).toPersistent(*this)) success = false;
159  }
160 
161  // WARNING: The code doesn't take thinning into account at the
162  // moment!!!
163 
164  // Reset the base class's variables:
165  m_persKeys.clear();
166  m_persIndices.clear();
167 
168  // Copy the info into the base class:
169  typename RefVector::const_iterator ref_itr = m_shortRefs.begin();
170  typename RefVector::const_iterator ref_end = m_shortRefs.end();
171  for( ; ref_itr != ref_end; ++ref_itr ) {
172  m_persKeys.push_back( ref_itr->elementLink().persKey() );
173  m_persIndices.push_back( ref_itr->elementLink().persIndex() );
174  }
175 
176  return success;
177 }
178 
179 
180 template <typename DOBJ>
181 bool
182 ElementLinkVector<DOBJ>::toPersistent
183  (std::vector<typename DataLinkVector::size_type>& shortrefs)
184 {
185  bool success = toPersistentDL();
186 
187  // set all ElementLink Refs to persistent state
188  shortrefs.reserve (m_shortRefs.size());
189  typename RefVector::iterator refIter = m_shortRefs.begin();
190  for (; refIter!= m_shortRefs.end(); ++refIter) {
191  typename DataLinkVector::size_type shortref;
192  if (! (*refIter).toPersistent(*this, shortref)) success = false;
193  shortrefs.push_back (shortref);
194  }
195 
196  return success;
197 }
198 
199 
200 template <typename DOBJ>
201 void
202 ElementLinkVector<DOBJ>::doRemap()
203 {
204  bool remapping = false;
205  typename RefVector::iterator refIter = m_shortRefs.begin();
206  for (; refIter!= m_shortRefs.end(); ++refIter) {
207  if (refIter->doRemap()) {
208  if (!remapping) {
209  m_hostDObjs.clear();
210  typename RefVector::iterator ri2 = m_shortRefs.begin();
211  for (; ri2 != refIter; ++ri2) {
212  addHostDObj (ri2->elementLink());
213  }
214  remapping = true;
215  }
216  }
217  if (remapping)
218  addHostDObj (refIter->elementLink());
219  }
220 }
221 
222 
223 // Set the vector of host data objects from @a dobjs.
224 // @a dobjs is destroyed.
225 // This is an error if the vector is not empty.
226 template <typename DOBJ>
227 void
228 ElementLinkVector<DOBJ>::moveHostDObjs
229  (DataLinkVector& dobjs)
230 {
231  if (!this->empty()) {
232  MsgStream log(Athena::getMessageSvc(), "ElementLink");
233  log << MSG::ERROR
234  << "ElementLinkVector::moveHostDObjs called on non-empty vector."
235  << endmsg;
236  throw std::runtime_error("ElementLinkVector::moveHistDObjs : vector not empty");
237  }
238  m_hostDObjs.swap (dobjs);
239 }
240 
241 
242 template <typename DOBJ>
243 void
244 ElementLinkVector<DOBJ>::push_back
245  (typename DataLinkVector::size_type nameIndex,
246  typename ElemLinkRef::index_type elementIndex)
247 {
248  m_shortRefs.push_back (ElemLinkRef (nameIndex, elementIndex, *this));
249 }
250 
251 template< typename DOBJ >
252 void ElementLinkVector< DOBJ >::
253 toTransient( uint64_t& /*dummy*/ ) {
254 
255  // A little sanity check:
256  assert( m_persKeys.size() == m_persIndices.size() );
257 
258  // Clear the object:
259  clear();
260 
261  // Now re-create the links based on the persistent info:
262  for( size_t i = 0; i < m_persKeys.size(); ++i ) {
263  push_back( ElemLink( m_persKeys[ i ], m_persIndices[ i ] ) );
264  }
265 
266  return;
267 }
268 
269 template< typename DOBJ >
270 void ElementLinkVector< DOBJ >::
271 toTransient( uint32_t& /*dummy*/ ) {
272 
273  // A little sanity check:
274  assert( m_persKeys.size() == m_persIndices.size() );
275 
276  // Clear the object:
277  clear();
278 
279  // Now re-create the links based on the persistent info:
280  for( size_t i = 0; i < m_persKeys.size(); ++i ) {
281  push_back( ElemLink( m_persKeys[ i ], m_persIndices[ i ] ) );
282  }
283 
284  return;
285 }
286 
287 template< typename DOBJ >
288 template< typename INDEX_TYPE >
289 void ElementLinkVector< DOBJ >::
290 toTransient( INDEX_TYPE& /*dummy*/ ) {
291 
292  REPORT_MESSAGE_WITH_CONTEXT( MSG::ERROR, "ElementLinkVector" )
293  << "Using direct ROOT I/O for type "
294  << System::typeinfoName( typeid( this ) )
295  << " not supported";
296 
297  return;
298 }
299 
300 template< typename DOBJ >
301 void ElementLinkVector< DOBJ >::
302 addHostDObj( const ElemLink& link ) {
303 
304  // Check if we already have it:
305  if( endHostDObjs() != findHostDObj( link ) ) {
306  return;
307  }
308 
309  //DataLink< DOBJ > dl( link.storagePolicy() );
310  DataLink< DOBJ > dl( link.key() );
311  if( ! dl.isDefault() ) {
312  m_hostDObjs.push_back( dl );
313 #ifdef __ELVDEBUG
314  std::cout << "addHostDObj added link "
315  << link.dataID() << "/" << link.index() << std::endl;
316 #endif
317  }
318 
319  return;
320 }