ATLAS Offline Software
ElementLinkVectorCnv_p1.icc
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 /** @file ElementLinkVectorCnv_p1.icc
6  * @brief This file contains the implementation for the ElementLinkVectorCnv_p1 template methods.
7  * @author Marcin.Nowak@cern.ch
8  **/
9 
10 #include <stdexcept>
11 
12 #include "AthLinks/ElementLinkVector.h"
13 #include "AthenaKernel/ThinningCache.h"
14 #include "AthenaKernel/ThinningDecisionBase.h"
15 #include "AthenaKernel/getThinningCache.h"
16 
17 //#include <iostream>
18 //using namespace std;
19 
20 //#define ELVEC_DEBUG
21 
22 
23 template <typename LINK_TYPE>
24 void
25 ElementLinkVectorCnv_p1<LINK_TYPE>::transToPers(const LinkVect_t& trans,
26  PersLinkVect_t& pers,
27  const SG::ThinningCache* cache,
28  MsgStream& msg) const
29 {
30  pers.m_elementRefs.clear();
31  pers.m_links.clear();
32 
33  LinkVect_t tmpTrans = trans;
34  tmpTrans.doRemap();
35 
36  // easy case first
37  if ( !cache ) {
38  std::vector<typename LinkVect_t::DataLinkVector::size_type> shortrefs;
39  tmpTrans.toPersistent(shortrefs);
40  // copy the container keys
41  m_DLinkVectorCnv.transToPers(&tmpTrans.hostDObjs(), &pers.m_links, msg);
42 
43  // copy the element links in the compact form
44  size_t link_n = tmpTrans.size();
45  pers.m_elementRefs.reserve(link_n);
46  for ( std::size_t i=0; i!=link_n; ++i ) {
47  typedef typename PersLinkVect_t::ElementRef PElemRef_t;
48  size_t idx = SG::ThinningDecisionBase::RemovedIdx;
49  if (shortrefs[i] != SG::ThinningDecisionBase::RemovedIdx)
50  idx = tmpTrans.elementIndex(i);
51  pers.m_elementRefs.push_back( PElemRef_t (idx, shortrefs[i]) );
52  }
53  return;
54  }
55 
56  // the not so easy case: thinning occured...
57 
58  // Note: we can't use ElementLinkVector::toPersistent.
59  // we have to first handle the DataLinks and then the elementlink refs
60  // otherwise we:
61  // - corrupt the ElementLinks
62  // - generate many-many ERRORs (when the EL points at a thinned away elmt)
63 
64  // set all DataLinks to persistent state
65  tmpTrans.toPersistentDL();
66 
67  // copy the container keys
68  m_DLinkVectorCnv.transToPers(&tmpTrans.hostDObjs(), &pers.m_links, msg);
69  //std::cout << "*** -- ElementLinkVectorCnv: KEY=" << *iter << std::endl;
70 
71  // copy the element links in the compact form
72  size_t link_n = tmpTrans.size();
73  pers.m_elementRefs.reserve(link_n);
74  typedef typename LinkVect_t::ElemLink EL;
75  for ( std::size_t ilink = 0; ilink != link_n; ++ilink ) {
76  // note the _copy_ of the original
77  // (needed for multi-stream thinning)
78  EL el = tmpTrans[ilink];
79  // here is the problem: in case the ElementLink was directly created w/
80  // only a pointer to the element, _and_ if the the pointed-at element
81  // has been thinned away, EL::index() will throw b/c
82  // IndexingPolicy::setIndex will fail.
83  std::size_t orig_idx = SG::ThinningDecisionBase::RemovedIdx;
84  try {
85  orig_idx = el.index();
86  } catch ( const SG::maybe_thinning_error& err ) {
87  // ok. that's the corner case we talked about above.
88  msg << MSG::DEBUG
89  << "caught a maybe_thinning_error: [" << err.what() << "]"
90  << endmsg
91  << "(this is an expected case of the EL-state-phase-space "
92  << "when thinning is active)"
93  << endmsg;
94  }
95  std::size_t idx = orig_idx;
96  if (cache) {
97  const SG::ThinningDecisionBase* dec = cache->thinning (el.key());
98  if (dec) {
99  idx = dec->index (idx);
100  }
101  }
102 
103  typename LinkVect_t::size_type shortref = 0;
104  if ( idx == SG::ThinningDecisionBase::RemovedIdx ) {
105  // that element has been thinned away.
106  shortref = idx; //< 'special' well-known value
107  } else {
108  // element not thinned away
109  typename LinkVect_t::DataLinkVector::iterator ihost =
110  tmpTrans.findHostDObj (el);
111  if (ihost != tmpTrans.endHostDObjs())
112  shortref = std::distance (tmpTrans.beginHostDObjs(), ihost);
113  else {
114  msg << MSG::WARNING
115  << "link not found in ElemLinkVector" << endmsg;
116  }
117  }
118  typedef typename PersLinkVect_t::ElementRef PersELRef;
119  pers.m_elementRefs.push_back( PersELRef (idx, shortref) );
120  }
121 }
122 
123 
124 template <typename LINK_TYPE>
125 void ElementLinkVectorCnv_p1<LINK_TYPE>::transToPers(const LinkVect_t& trans,
126  PersLinkVect_t& pers,
127  MsgStream& msg) const
128 {
129  transToPers (trans, pers,
130  SG::getThinningCache(),
131  msg);
132 }
133 
134 
135 template <typename LINK_TYPE >
136 void ElementLinkVectorCnv_p1< LINK_TYPE >::persToTrans(const PersLinkVect_t& pers, LinkVect_t& trans, MsgStream& msg) const
137 {
138  // copy the container keys
139  typename LinkVect_t::DataLinkVector dl;
140  m_DLinkVectorCnv.persToTrans(&pers.m_links, &dl, msg);
141  trans.clear();
142  trans.moveHostDObjs (dl);
143  trans.toTransient();
144  // cout << "*** -- ElementLinkVectorCnv: KEY=" << *iter << endl;
145  // copy the element links in the compact form
146  size_t link_n = pers.m_elementRefs.size();
147  trans.reserve(link_n);
148  typename PersLinkVect_t::ElementRefVector::const_iterator link_iter = pers.m_elementRefs.begin();
149  while(link_n--) {
150  // This test needed for 32/64 bit compatibility.
151  if ( link_iter->m_nameIndex == static_cast<uint32_t>(SG::ThinningDecisionBase::RemovedIdx) &&
152  link_iter->m_elementIndex == static_cast<Index_t>(SG::ThinningDecisionBase::RemovedIdx) )
153  {
154  // thinned-away element...
155  trans.push_back (SG::ThinningDecisionBase::RemovedIdx,
156  SG::ThinningDecisionBase::RemovedIdx);
157  }
158  else
159  trans.push_back (link_iter->m_nameIndex, link_iter->m_elementIndex);
160 
161  #ifdef ELVEC_DEBUG
162  msg << MSG::DEBUG
163  << "ElementLinkVectorCnv_p1::PersToTrans(): KEY="
164  << pers->m_links[link_iter->m_nameIndex].m_link
165  << ", IDX=" << link_iter->m_elementIndex
166  << endmsg;
167  #endif
168  ++link_iter;
169  }
170 }
171 
172 
173 
174 
175 template <typename LINK_TYPE>
176 inline
177 void
178 ElementLinkVectorCnv_p1<LINK_TYPE>
179 ::transToPers(const LinkVect_t* trans, PersLinkVect_t* pers, MsgStream& msg) const
180 {
181  this->transToPers(*trans, *pers, msg);
182 }
183 
184 
185 template <typename LINK_TYPE >
186 inline
187 void
188 ElementLinkVectorCnv_p1< LINK_TYPE >
189 ::persToTrans(const PersLinkVect_t* pers, LinkVect_t* trans, MsgStream& msg) const
190 {
191  this->persToTrans(*pers, *trans, msg);
192 }