ATLAS Offline Software
Loading...
Searching...
No Matches
PhaseIIInDetRawDataContainer.h
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2026 CERN for the benefit of the ATLAS collaboration
3 */
4#ifndef PHASEII_RAWDATACONTAINER_H
5#define PHASEII_RAWDATACONTAINER_H
6
7#include <array>
8#include <vector>
9#include <cassert>
10#include <cstdint>
11#include <cstring>
12#include <atomic>
13
14#include "ProxyContainer.h"
15#include "ContainerList.h"
16
17namespace PhaseII {
18
19 template <typename Type>
20 concept isAtomic = requires( Type a, typename Type::value_type b ) { a.compare_exchange_weak(b,b); };
21
22 // test whether the given container type has an error container
23 template <typename T_DataContainer>
24 concept hasErrors = requires(T_DataContainer &a, unsigned int idx) { a.errors()[idx]; };
25
26 template <typename T>
27 struct GetValue {
28 static auto value(const T &value) requires ( !isAtomic<T> ) { return value; }
29 static auto value(const T &value) requires ( isAtomic<T> ) { return value.load(); }
30 };
31
38 struct DataRange {
39 using RangeBeginIndex_t = std::uint32_t;
40 using RangeSize_t = std::uint16_t;
41 using ContainerIndex_t = std::uint16_t;
42 // wrap members of the DataRange into union to convince clang to
43 // use this type as a value for a lock free atomic.
44 union {
45 struct Range {
50 std::uint64_t m_compactRange;
52
53 DataRange() : m_payload{.m_compactRange = std::uint64_t{} }{}
54 DataRange(std::uint64_t compact_range) : m_payload{.m_compactRange = compact_range }{}
55 DataRange(unsigned int begin_val, unsigned int n, unsigned int idx)
56 : m_payload{ .m_range = {static_cast<std::uint32_t>(begin_val), static_cast<std::uint16_t>(n), static_cast<std::uint16_t>(idx)} }
57 {
58 assert(begin_val<std::numeric_limits<std::uint32_t>::max());
59 assert(n<std::numeric_limits<std::uint16_t>::max());
60 assert(idx<std::numeric_limits<std::uint16_t>::max());
61 }
62 DataRange(std::uint32_t begin_val, std::uint16_t n, std::uint16_t idx)
63 : m_payload{ .m_range= {begin_val, n, idx} }
64 {
65 }
66 std::uint64_t makeCompact() const {
67 static_assert( sizeof(m_payload.m_range) == sizeof(std::uint64_t));
68 return m_payload.m_compactRange;
69 }
70
71 void setSize(RangeSize_t new_size) { m_payload.m_range.m_n=new_size; }
72 std::uint16_t containerIndex() const { return m_payload.m_range.m_containerIndex; }
73 unsigned int beginIndex() const { return m_payload.m_range.m_beginIndex;}
74 unsigned int endIndex() const { return m_payload.m_range.m_beginIndex + m_payload.m_range.m_n; }
75 std::uint16_t size() const { return m_payload.m_range.m_n; }
76 bool empty() const { return m_payload.m_range.m_n==0u; }
77 template <typename T_ElementIndex, typename T_ContainerIndex>
78 static DataRange makeDataRange(T_ElementIndex begin_index,
79 T_ElementIndex end_index,
80 T_ContainerIndex container_index) {
81 // ensure that the inputs are within the allowed range in (debug build only!)
82 // @TODO check some of these always during runtime ?
83 // Replace this convenience method into a constructor ? But an exception could be thrown here.
84 assert( end_index >= begin_index ) ;
85 assert( static_cast<std::uint32_t>(begin_index) == begin_index);
86 assert( static_cast<std::size_t>(end_index - begin_index) < std::numeric_limits<std::uint16_t>::max());
87 assert( static_cast<std::uint16_t>(container_index) == container_index);
88 return DataRange(static_cast<std::uint32_t>(begin_index),
89 static_cast<std::uint16_t>(end_index - begin_index),
90 static_cast<std::uint16_t>(container_index));
91 }
92 };
93
94
108 template <class T_DataContainer, class T_RangeType>
110 public:
111 using DataContainerType = T_DataContainer;
112 using T_RangeTypeBase = decltype( GetValue<T_RangeType>::value(T_RangeType{}));
113
117 IndexedRanges(unsigned int n_ranges, unsigned int container_list_size)
118 : m_containers(container_list_size), m_range(n_ranges) {}
119
126 bool registerOrEraseNewData(unsigned int index, const T_RangeTypeBase &new_range)
127 {
128 assert (index < m_range.size());
129 assert( new_range.containerIndex() < m_containers.size() );
130 T_RangeTypeBase is_range = m_range[index];
131 if (is_range.size() != new_range.size()) {
132 assert(is_range.empty());
133 if (update(index, is_range, new_range)) {
134 return true;
135 }
136 }
137 // it is assumed that data is always added at the end and then registered.
138 assert( new_range.beginIndex() + new_range.size() == m_containers[new_range.containerIndex()].size());
139 m_containers[new_range.containerIndex()].erase_back(new_range.beginIndex());
140 return false;
141 }
142
143 // @TODO declare protected ?
144 bool update(unsigned int index, T_RangeTypeBase & is_range, const T_RangeTypeBase &new_range) requires( isAtomic<T_RangeType> )
145 {
146 assert( index < m_range.size());
147 return m_range[index].compare_exchange_weak(is_range, new_range);
148 }
149
150 // @TODO declare protected ?
151 bool update(unsigned int index, [[maybe_unused]] T_RangeTypeBase & is_range, const T_RangeTypeBase &new_range) requires(!isAtomic<T_RangeType>)
152 {
153 assert( index < m_range.size());
154 m_range[index]=new_range;
155 return true;
156 }
157
160 const T_DataContainer &data(unsigned int container_index) const
161 { assert(container_index<m_containers.size()); return m_containers[container_index]; }
162
165 T_DataContainer &data(unsigned int container_index)
166 { assert(container_index<m_containers.size()); return m_containers[container_index]; }
167
172 const T_RangeType &range(unsigned int index) const {
173 assert(index < m_range.size());
174 return m_range[index];
175 }
176
178 std::size_t size() const { return m_range.size(); }
180 std::size_t empty() const { return m_range.empty(); }
181
183 std::size_t containerListCapacity() const { return m_containers.size(); }
184
186 const auto &errorContainer(unsigned int container_index) const requires(hasErrors<T_DataContainer>) {
187 assert( container_index < m_containers.size() );
188 assert( m_containers[container_index].errors().empty() || m_containers[container_index].errors().size() == m_range.size());
189 return m_containers[container_index].errors();
190 }
191
192 auto &errorContainer(unsigned int container_index) requires(hasErrors<T_DataContainer>) {
193 assert( container_index < m_containers.size() );
194 return m_containers[container_index].errors();
195 }
196
197 protected:
199 std::vector<T_RangeType> m_range;
200 };
201
202
210 unsigned int m_beginIndex {};
211 unsigned int m_endIndex {};
212 unsigned int m_rangeIndex {};
213
215 unsigned int beginIndex() const { return m_beginIndex; }
217 unsigned int endIndex() const { return m_endIndex; }
219 bool empty() const { return m_endIndex == m_beginIndex; }
220
224 const unsigned int &rangeIndex() const { return m_rangeIndex; }
225
226 // only used in unit test
227 bool operator==(const IndexWithRange &other) const {
228 // should only be executed if the indices refer to the same range
229 // thus the cached begin index should always be identical, and
230 // comparison is limited to the minimum, which is only sufficient
231 // if the the two indices refer to the same range, which is the
232 // case when this comparison would be done as part of a range based
233 // for loop.
234 assert(m_endIndex == other.m_endIndex);
235 assert(m_beginIndex == other.m_beginIndex);
236 return m_rangeIndex == other.m_rangeIndex;
237 }
238 };
239
244 template <std::size_t NDim>
246 public:
247
249 bool isValid(unsigned int index) const { assert( m_coordinates.size() == m_word.size()); return index < m_coordinates.size(); }
250
252 const std::array<std::int16_t,NDim> &coordinates(unsigned int index) const { assert(isValid(index)); return m_coordinates[index]; }
254 std::array<std::int16_t,NDim> &coordinates(unsigned int index) { assert(isValid(index)); return m_coordinates[index]; }
256 const std::uint32_t &dataWord(unsigned int index) const { assert(isValid(index)); return m_word[index]; }
258 std::uint32_t &dataWord(unsigned int index) { assert(isValid(index)); return m_word[index]; }
259
260 // Test whether the container is in a sane state (for debugging).
261 // The container is in a sane state if the number elements in all the vectors are synchronised.
262 bool isSane() const { return m_coordinates.size() == m_word.size(); }
263
265 std::size_t size() const { assert(isSane()); return m_coordinates.size(); }
267 bool empty() const { assert(isSane()); return m_coordinates.empty(); }
269 std::size_t capacity() const { assert(m_coordinates.capacity() == m_word.capacity()); return m_coordinates.capacity(); }
270
272 void reserve(std::size_t new_capacity) {
273 m_coordinates.reserve(new_capacity);
274 m_word.reserve(new_capacity);
275 assert(isSane() && m_coordinates.capacity() == m_word.capacity());
276 }
277
281 void emplace_back(std::array<std::int16_t,NDim> &&coordinates, std::uint32_t data_word) {
282 // @TODO should bail out if container is filled concurrently and the
283 // size is equal to the capacity, but the container does not know.
284 m_coordinates.emplace_back(std::move(coordinates));
285 m_word.emplace_back(data_word);
286 assert(isSane());
287 }
288
294 void erase_back( unsigned int begin_index) {
295 assert( begin_index <= m_coordinates.size());
296 m_coordinates.erase( m_coordinates.begin()+begin_index, m_coordinates.end());
297 m_word.erase( m_word.begin()+begin_index, m_word.end());
298 assert(isSane());
299 }
300
307 static constexpr int unpack(std::uint32_t mask, unsigned int shift, unsigned int word) {
308 return static_cast<int>( (word >> shift ) & mask );
309 }
310
319 static constexpr std::uint32_t pack(std::uint32_t mask, unsigned int shift, int input) {
320 // test that packing is loss-less
321 assert( static_cast<int>(static_cast<std::uint32_t>(input) & mask) ==input );
322 return static_cast<std::uint32_t>( (input & mask) << shift );
323 }
324
330 void move(InDetRawDataContainer &dest, unsigned int start_index) {
331 unsigned int copy_n_elements=size()-start_index;
332 dest.m_coordinates.resize(copy_n_elements);
333 dest.m_word.resize(copy_n_elements);
334 std::memcpy(dest.m_coordinates.data(),m_coordinates.data()+start_index,copy_n_elements*sizeof(typename decltype(m_coordinates)::value_type));
335 std::memcpy(dest.m_word.data(), m_word.data()+start_index, copy_n_elements*sizeof(typename decltype(m_word)::value_type) );
336 this->erase_back(start_index);
337 }
338 private:
339 std::vector<std::array<std::int16_t,NDim> > m_coordinates;
340 std::vector<std::uint32_t> m_word;
341 };
342
343
344 using namespace Utils;
345
352 template <class T_RawDataContainer, AccessPolicy accessPolicy=AccessPolicy::ReadOnly>
353 class RawDataProxyBase : public ContainerProxyBase<T_RawDataContainer, unsigned int, accessPolicy >::template ElementProxyBase<accessPolicy> {
354 public:
356 using BASE::BASE;
357
358 const auto &coordinates() const {
359 return this->container().coordinates(this->index());
360 }
361 auto &coordinates() requires (accessPolicy == AccessPolicy::ReadWrite) {
362 return this->container().coordinates(this->index());
363 }
364 const auto &dataWord() const {
365 return this->container().dataWord(this->index());
366 }
367 auto &dataWord() requires (accessPolicy == AccessPolicy::ReadWrite) {
368 return this->container().dataWord(this->index());
369 }
370 };
371
378 template <class T_RawDataContainer, class T_RawDataProxy, AccessPolicy accessPolicy=AccessPolicy::ReadOnly>
379 class RawDataContainerProxy : public ContainerProxy<T_RawDataContainer,
380 RawDataContainerProxy<T_RawDataContainer, T_RawDataProxy, accessPolicy>,
381 T_RawDataProxy,
382 IndexWithRange,
383 accessPolicy > {
384 public:
385 using BASE = ContainerProxy<T_RawDataContainer,
387 T_RawDataProxy,
389 accessPolicy > ;
390
391 using BASE::BASE;
392
394 static unsigned int beginIndex([[maybe_unused]] const T_RawDataContainer *container, const IndexWithRange &range)
395 {
396 assert( range.empty() || container);
397 return range.beginIndex();
398 }
399
400 static unsigned int endIndex([[maybe_unused]] const T_RawDataContainer *container, const IndexWithRange &range) {
401 assert( range.empty() || container);
402 return range.endIndex();
403 }
404
405 static unsigned int nextElementIndex([[maybe_unused]] const T_RawDataContainer *container, unsigned int element_index)
406 {
407 assert( element_index < container->size());
408 return ++element_index;
409 }
410
412 const unsigned int &identifyHash() const { return this->index().rangeIndex(); }
413
414 // convenience methods
415 unsigned int beginIndex() const { return this->index().beginIndex(); }
416 unsigned int endIndex() const { return this->index().endIndex(); }
417
418 };
419
420 namespace RawData {
421 namespace details {
422 // to define the proxy that should be used for the given raw data container.
423 template <class T_RawDataContainer>
424 struct traits {
425 template <AccessPolicy accessPolicy>
427 };
428 }
429 }
430
438 // @TODO add concepts for T_RawDataContainerCollection
439 template <class T_RawDataContainerCollection, class T_RawDataProxy, AccessPolicy accessPolicy=AccessPolicy::ReadOnly>
440 class ContainerProxyAdapter : public ContainerProxyBase<T_RawDataContainerCollection,
441 unsigned int,
442 accessPolicy >::template ElementProxyBase<accessPolicy>
443 {
444 using T_Range = typename T_RawDataContainerCollection::T_RangeTypeBase;
445 using T_RawDataContainer = std::remove_cvref_t<decltype(std::declval<T_RawDataContainerCollection>().data(std::uint32_t{}))>;
446 // Create a special index which also provided the child element range.
447 static IndexWithRange getIndexWithRange(const T_RawDataContainerCollection &container, unsigned int module_index) {
448 T_Range range = container.range(module_index); // container has to implement range(module_index)
449 return IndexWithRange(range.beginIndex(),
450 range.endIndex(),
451 module_index);
452 }
453 // Get from this container collection the actual container which contains the hit data (read only).
454 static const T_RawDataContainer *getRawDataContainer(const T_RawDataContainerCollection &container, unsigned int module_index) {
455 T_Range range = container.range(module_index);
456 return &(container.data(range.containerIndex()));
457 }
458 // Get from this container collection the actual container which contains the hit data (read/write).
459 static T_RawDataContainer *getRawDataContainer(T_RawDataContainerCollection &container, unsigned int module_index)
460 requires( accessPolicy == AccessPolicy::ReadWrite)
461 {
462 T_Range range = container.range(module_index);
463 return &(container.data(range.containerIndex()));
464 }
465 public:
467 using BASE::BASE;
468
472 create(T_RawDataContainerCollection *container, unsigned int module_index)
473 {
474 assert(container);
476 getIndexWithRange(*container,module_index) );
477 return proxy;
478 }
479
484 create(const T_RawDataContainerCollection *container, unsigned int module_index)
485 requires(accessPolicy==AccessPolicy::ReadOnly)
486 {
487 assert(container);
489 getIndexWithRange(*container,module_index) );
490 return proxy;
491 }
492
497 static unsigned int getOriginalElementIndex(const IndexWithRange &index) {
498 return index.rangeIndex();
499 }
500 };
501
503 template <class T_RawDataContainerCollection, class T_RawDataProxy, AccessPolicy accessPolicy=AccessPolicy::ReadOnly>
504 class ContainerCollectionProxy : public ContainerProxy<T_RawDataContainerCollection,
505 ContainerCollectionProxy<T_RawDataContainerCollection, T_RawDataProxy, accessPolicy>,
506 ContainerProxyAdapter<T_RawDataContainerCollection, T_RawDataProxy,accessPolicy>,
507 RootNodeIndex,
508 accessPolicy > {
509 using BASE=ContainerProxy<T_RawDataContainerCollection,
513 accessPolicy >;
514 using BASE::BASE;
515 };
516
518 template <class T_RawDataContainer, AccessPolicy accessPolicy=AccessPolicy::ReadOnly>
526
528 template <class T_RawDataContainerCollection>
529 inline auto makeRawDataCollectionProxy(const T_RawDataContainerCollection &collection) {
530 using T_RawDataContainer = typename T_RawDataContainerCollection::DataContainerType;
532 }
533
535 template <class T_RawDataContainerCollection>
536 inline auto makeRawDataCollectionProxy(T_RawDataContainerCollection &collection) {
537 using T_RawDataContainer = typename T_RawDataContainerCollection::DataContainerType;
539 }
540}
541#endif
bool isValid(const T &p)
Av: we implement here an ATLAS-sepcific convention: all particles which are 99xxxxx are fine.
Definition AtlasPID.h:878
float m_range[NbCaloPart][2]
static Double_t a
static const Attributes_t empty
Helper class which provides a possibly dynamically growing list of containers suitable for a multi-th...
size_t size() const
Duplicate of fullSize for backwards compatability.
Helper class to represent the top level proxy which provides per module proxy objects which provide t...
ContainerProxy< T_RawDataContainerCollection, ContainerCollectionProxy< T_RawDataContainerCollection, T_RawDataProxy, accessPolicy >, ContainerProxyAdapter< T_RawDataContainerCollection, T_RawDataProxy, accessPolicy >, RootNodeIndex, accessPolicy > BASE
An adapter to create a container proxy from a range index which defines the actual element container ...
std::remove_cvref_t< decltype(std::declval< T_RawDataContainerCollection >().data(std::uint32_t{}))> T_RawDataContainer
static RawDataContainerProxy< T_RawDataContainer, T_RawDataProxy, AccessPolicy::ReadOnly > create(const T_RawDataContainerCollection *container, unsigned int module_index)
Create the actual container proxy for the elements this proxy refers to.
static T_RawDataContainer * getRawDataContainer(T_RawDataContainerCollection &container, unsigned int module_index)
static IndexWithRange getIndexWithRange(const T_RawDataContainerCollection &container, unsigned int module_index)
typename ContainerProxyBase< T_RawDataContainerCollection, unsigned int, accessPolicy >::template ElementProxyBase< accessPolicy > BASE
typename T_RawDataContainerCollection::T_RangeTypeBase T_Range
static unsigned int getOriginalElementIndex(const IndexWithRange &index)
Supporting method for "converted" proxies resulting from the methods above to recover the original "c...
static const T_RawDataContainer * getRawDataContainer(const T_RawDataContainerCollection &container, unsigned int module_index)
static RawDataContainerProxy< T_RawDataContainer, T_RawDataProxy, accessPolicy > create(T_RawDataContainerCollection *container, unsigned int module_index)
Create the actual container proxy for the elements this proxy refers to.
Base raw data container which provides coordinates of a certain dimension and a data word per RDO (ra...
void emplace_back(std::array< std::int16_t, NDim > &&coordinates, std::uint32_t data_word)
Add a new RDO to the end of this container.
std::vector< std::array< std::int16_t, NDim > > m_coordinates
static constexpr int unpack(std::uint32_t mask, unsigned int shift, unsigned int word)
extract a value from a bit packed word.
std::size_t capacity() const
the maximum number RDOs this container can hold without reallocation.
void move(InDetRawDataContainer &dest, unsigned int start_index)
Move the coordinates and the data word of a certain number of elements at the end to a new container.
const std::array< std::int16_t, NDim > & coordinates(unsigned int index) const
return the coordinates i.e. column, row or strip of a certain RDO (read only).
std::size_t size() const
total number of RDOs which are in this container.
bool isValid(unsigned int index) const
return true if the index refers to an element in the container
static constexpr std::uint32_t pack(std::uint32_t mask, unsigned int shift, int input)
Create a bit-packed word from an input value.
bool empty() const
test whether the container is empty i.e. does not contain any RDOs
std::array< std::int16_t, NDim > & coordinates(unsigned int index)
return the coordinates i.e. column, row or strip of a certain RDO.
const std::uint32_t & dataWord(unsigned int index) const
return the packed data word of of a certain RDO (read only).
void reserve(std::size_t new_capacity)
reserve space for a certain number of RDOs.
std::uint32_t & dataWord(unsigned int index)
return the packed data word of of a certain RDO.
void erase_back(unsigned int begin_index)
erase the elements at the end of the container
Helper class to associate ranges of elements in multiple containers to a contiguous index.
auto & errorContainer(unsigned int container_index)
if there is an associated error container get it (read/write access).
T_DataContainer & data(unsigned int container_index)
Get an existing container from the container collection.
IndexedRanges(unsigned int n_ranges, unsigned int container_list_size)
create a container collection for n_ranges and a certain maximum number of containers.
bool update(unsigned int index, T_RangeTypeBase &is_range, const T_RangeTypeBase &new_range)
update a range (version for a "non-atomic" range)
const auto & errorContainer(unsigned int container_index) const
if there is an associated error container get it.
std::size_t empty() const
return true there are no element ranges.
bool update(unsigned int index, T_RangeTypeBase &is_range, const T_RangeTypeBase &new_range)
const T_DataContainer & data(unsigned int container_index) const
Get an existing container from the container collection (read only).
const T_RangeType & range(unsigned int index) const
Get a specific element range.
bool registerOrEraseNewData(unsigned int index, const T_RangeTypeBase &new_range)
register an element range or erase the elements of this range.
decltype(GetValue< T_RangeType >::value(T_RangeType{})) T_RangeTypeBase
std::size_t size() const
return the total number of element ranges.
A proxy providing access to the RDOs of a single module.
const unsigned int & identifyHash() const
method which returns the identifier hash of the module this proxy represents.
static unsigned int beginIndex(const T_RawDataContainer *container, const IndexWithRange &range)
method which returns the index of the first child element this proxy represents
static unsigned int endIndex(const T_RawDataContainer *container, const IndexWithRange &range)
method which returns the index of the element after the last child element this proxy represents
static unsigned int nextElementIndex(const T_RawDataContainer *container, unsigned int element_index)
method which returns the element which follows the element specified by element_index
ContainerProxy< T_RawDataContainer, RawDataContainerProxy< T_RawDataContainer, T_RawDataProxy, accessPolicy >, T_RawDataProxy, IndexWithRange, accessPolicy > BASE
typename ContainerProxyBase< T_RawDataContainer, unsigned int, accessPolicy >::template ElementProxyBase< accessPolicy > BASE
A Range describes the possible ranges for the field values of an ExpandedIdentifier.
auto makeRawDataCollectionProxy(const T_RawDataContainerCollection &collection)
Create the top level container proxy for an RDO container collection (read only).
Definition index.py:1
STL namespace.
RangeSize_t m_n
the number of elements in this range.
RangeBeginIndex_t m_beginIndex
the index of the first element in the range in the container defined by the container index
DataRange(std::uint32_t begin_val, std::uint16_t n, std::uint16_t idx)
unsigned int beginIndex() const
std::uint64_t makeCompact() const
DataRange(std::uint64_t compact_range)
union PhaseII::DataRange::@115366361000146103022305316242135000036157260104 m_payload
struct PhaseII::DataRange::@115366361000146103022305316242135000036157260104::Range m_range
std::uint16_t containerIndex() const
static DataRange makeDataRange(T_ElementIndex begin_index, T_ElementIndex end_index, T_ContainerIndex container_index)
void setSize(RangeSize_t new_size)
ContainerIndex_t m_containerIndex
the index which identifies the the container within a container collection
DataRange(unsigned int begin_val, unsigned int n, unsigned int idx)
static auto value(const T &value)
static auto value(const T &value)
Helper class to be used in conjunction with ProxyContainers.
const unsigned int & rangeIndex() const
the index which identifies this range within its parent.
bool empty() const
return true if this range does not contain any elements.
bool operator==(const IndexWithRange &other) const
unsigned int beginIndex() const
the first element in the range
unsigned int m_endIndex
index after the last child element of this range
unsigned int m_beginIndex
index of the first child element in the range
unsigned int endIndex() const
the index of the element after the last element
unsigned int m_rangeIndex
the index if the element which is the parent of the children where the index may refer to a different...
helper class to define all the proxies for a RDO container.
PhaseII::RawDataContainerProxy< T_RawDataContainer, RawDataProxy, accessPolicy > RawDataContainerProxy
PhaseII::ContainerCollectionProxy< ContainerCollection, RawDataProxy, accessPolicy > ContainerCollectionProxy
typename RawData::details::traits< T_RawDataContainer >::template RawDataProxy< accessPolicy > RawDataProxy
PhaseII::IndexedRanges< T_RawDataContainer, std::atomic< PhaseII::DataRange > > ContainerCollection
PhaseII::ContainerProxyAdapter< ContainerCollection, RawDataProxy, accessPolicy > ContainerProxyAdapter
RawDataProxyBase< T_RawDataContainer, accessPolicy > RawDataProxy
Base class of a container proxy.
Helper struct to indicate the "index" of a top level container proxy.