ATLAS Offline Software
JaggedVecVector.icc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2002-2024 CERN for the benefit of the ATLAS collaboration.
3  */
4 /**
5  * @file AthContainers/tools/JaggedVecVector.icc
6  * @author scott snyder <snyder@bnl.gov>
7  * @date Mar, 2024
8  * @brief Implementation of @c IAuxTypeVector for @c JaggedVecElt types.
9  */
10 
11 
12 #include "AthContainers/AuxTypeRegistry.h"
13 
14 
15 namespace SG {
16 
17 
18 /**
19  * @brief Constructor.
20  * @param auxid The auxid of the variable this vector represents.
21  * @param vecPtr Pointer to the object.
22  * @param linkedVec Interface for the linked vector of DataLinks.
23  * @param ownFlag If true, take ownership of the object.
24  */
25 template <class T, class ALLOC>
26 JaggedVecVectorHolder<T, ALLOC>::JaggedVecVectorHolder
27  (auxid_t auxid,
28  vector_type* vecPtr,
29  IAuxTypeVector* linkedVec,
30  bool ownFlag)
31  : Base (auxid, vecPtr, ownFlag, false),
32  m_linkedVec (linkedVec)
33 {
34 }
35 
36 
37 /**
38  * @brief Change the size of the vector.
39  * @param sz The new vector size.
40  * Returns true if it is known that iterators have not been invalidated;
41  * false otherwise.
42  */
43 template <class T, class ALLOC>
44 inline
45 bool JaggedVecVectorHolder<T, ALLOC>::resize (size_t sz)
46 {
47  bool valid = true;
48  vector_type& vec = this->vec();
49  Elt zero;
50  if (sz < vec.size()) {
51  size_t payload_sz = sz > 0 ? vec[sz-1].end() : 0;
52  valid = m_linkedVec->resize (payload_sz);
53  }
54  else if (vec.size() > 0) {
55  size_t payload_sz = vec.back().end();
56  zero = Elt (payload_sz);
57  }
58  const void* orig = vec.data();
59  vec.resize (sz, zero);
60  this->storeDataSpan();
61  return valid && vec.data() == orig;
62 }
63 
64 
65 /**
66  * @brief Shift the elements of the vector.
67  * @param pos The starting index for the shift.
68  * @param offs The (signed) amount of the shift.
69  *
70  * This operation shifts the elements in the vectors for all
71  * aux data items, to implement an insertion or deletion.
72  * @c offs may be either positive or negative.
73  *
74  * If @c offs is positive, then the container is growing.
75  * The container size should be increased by @c offs,
76  * the element at @c pos moved to @c pos + @c offs,
77  * and similarly for following elements.
78  * The elements between @c pos and @c pos + @c offs should
79  * be default-initialized.
80  *
81  * If @c offs is negative, then the container is shrinking.
82  * The element at @c pos should be moved to @c pos + @c offs,
83  * and similarly for following elements.
84  * The container should then be shrunk by @c -offs elements
85  * (running destructors as appropriate).
86  *
87  * Returns true if it is known that iterators have not been invalidated;
88  * false otherwise. (Will always return false when increasing the size
89  * of an empty container.)
90  */
91 template <class T, class ALLOC>
92 bool JaggedVecVectorHolder<T, ALLOC>::shift (size_t pos, ptrdiff_t offs)
93 {
94  vector_type& vec = this->vec();
95  if (offs < 0) {
96  if (-offs > static_cast<ptrdiff_t>(pos)) offs = -pos;
97  size_t ppos = pos < vec.size() ? vec[pos].begin(pos) : m_linkedVec->size();
98  ptrdiff_t poffs = - (ppos - vec[pos+offs].begin(pos+offs));
99  m_linkedVec->shift (ppos, poffs);
100  vec.erase (vec.begin() + pos+offs, vec.begin() + pos);
101  std::for_each (vec.begin() + pos+offs, vec.end(), Shift (poffs));
102  this->storeDataSpan();
103  return true;
104  }
105  else if (offs > 0) {
106  const void* orig = vec.data();
107  size_t oldsz = vec.size();
108  Elt zero;
109  if (!vec.empty()) {
110  index_type end = vec.back().end();
111  zero = Elt (end);
112  }
113  // Add to the end, zero-filled.
114  vec.resize (vec.size() + offs, zero);
115  if (oldsz != pos) {
116  // Shift existing elements. If we're just extending,
117  // then we can skip this.
118  std::copy (vec.rbegin() + offs,
119  vec.rbegin() + (offs+oldsz-pos),
120  vec.rbegin());
121  if (pos == 0) {
122  zero = Elt (0);
123  }
124  else {
125  index_type end = vec[pos-1].end();
126  zero = Elt (end);
127  }
128  std::fill_n (vec.begin() + pos, offs, zero);
129  }
130  this->storeDataSpan();
131  return vec.data() == orig;
132  }
133  return true;
134 }
135 
136 
137 /**
138  * @brief Insert elements into the vector via move semantics.
139  * @param pos The starting index of the insertion.
140  * @param src Start of the vector containing the range of elements to insert.
141  * @param src_pos Position of the first element to insert.
142  * @param src_n Number of elements to insert.
143  * @param srcStore The source store.
144  *
145  * @c beg and @c end define a range of container elements, with length
146  * @c len defined by the difference of the pointers divided by the
147  * element size.
148  *
149  * The size of the container will be increased by @c len, with the elements
150  * starting at @c pos copied to @c pos+len.
151  *
152  * The contents of the source range will then be moved to our vector
153  * starting at @c pos. This will be done via move semantics if possible;
154  * otherwise, it will be done with a copy.
155  *
156  * Returns true if it is known that the vector's memory did not move,
157  * false otherwise.
158  */
159 template <class T, class ALLOC>
160 bool JaggedVecVectorHolder<T, ALLOC>::insertMove
161  (size_t pos, void* src, size_t src_pos, size_t src_n, IAuxStore& srcStore)
162 {
163  if (src_n <= 0) return true;
164  element_type* srcp = reinterpret_cast<element_type*> (src);
165  element_type* beg = srcp + src_pos;
166  element_type* end = beg + src_n;
167 
168  vector_type& vec = this->vec();
169  const element_type* orig = vec.data();
170  vec.insert (vec.begin() + pos, beg, end);
171  size_t begidx = srcp[src_pos].begin(src_pos);
172  size_t npayload = beg[src_n-1].end() - begidx;
173  size_t ppos = vec[pos].begin(pos);
174  IAuxTypeVector* srcPayloadVec = srcStore.linkedVector (this->auxid());
175  T* srcPayload = reinterpret_cast<T*> (srcPayloadVec->toPtr());
176  bool pflag = m_linkedVec->insertMove (ppos,
177  srcPayload,
178  begidx,
179  npayload,
180  srcStore);
181  std::for_each (vec.begin() + pos, vec.begin() + pos + src_n,
182  Shift (ppos - begidx));
183  std::for_each (vec.begin() + pos + src_n, vec.end(),
184  Shift (npayload));
185  this->storeDataSpan();
186  return pflag && (vec.data() == orig);
187 }
188 
189 
190 //*****************************************************************************
191 
192 
193 /**
194  * @brief Constructor. Makes a new vector.
195  * @param auxid The auxid of the variable this vector represents.
196  * @param size Initial size of the new vector.
197  * @param capacity Initial capacity of the new vector.
198  * @param linkedVec Ownership of the linked vector.
199  */
200 template <class HOLDER>
201 JaggedVecVectorT<HOLDER>::JaggedVecVectorT (auxid_t auxid,
202  size_t size,
203  size_t capacity,
204  std::unique_ptr<IAuxTypeVector> linkedVec)
205  : Base (auxid, &m_vec, linkedVec.get(), false),
206  m_linkedVecHolder (std::move (linkedVec))
207 {
208  m_vec.reserve (capacity);
209  m_vec.resize (size);
210 }
211 
212 
213 /**
214  * @brief Copy constructor.
215  */
216 template <class HOLDER>
217 JaggedVecVectorT<HOLDER>::JaggedVecVectorT (const JaggedVecVectorT& other)
218  : Base (other.auxid(), &m_vec, false, false),
219  m_vec (other.m_vec),
220  m_linkedVecHolder (other.m_linkedVec->clone())
221 {
222  Base::m_linkedVec = m_linkedVecHolder.get();
223 }
224 
225 
226 /**
227  * @brief Move constructor.
228  */
229 template <class HOLDER>
230 JaggedVecVectorT<HOLDER>::JaggedVecVectorT (JaggedVecVectorT&& other)
231  : Base (other.auxid(), &m_vec, false, other.m_linkedVec),
232  m_vec (std::move (other.m_vec)),
233  m_linkedVecHolder (std::move (other.m_linkedVecHolder))
234 {
235 }
236 
237 
238 /**
239  * @brief Make a copy of this vector.
240  */
241 template <class HOLDER>
242 inline
243 std::unique_ptr<IAuxTypeVector> JaggedVecVectorT<HOLDER>::clone() const
244 {
245  return std::make_unique<JaggedVecVectorT> (*this);
246 }
247 
248 
249 /**
250  * @brief Return ownership of the linked vector.
251  */
252 template <class HOLDER>
253 inline
254 std::unique_ptr<IAuxTypeVector> JaggedVecVectorT<HOLDER>::linkedVector()
255 {
256  return std::move (m_linkedVecHolder);
257 }
258 
259 
260 } // namespace SG