ATLAS Offline Software
Loading...
Searching...
No Matches
ContainerList.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 CONTAINERLIST_H
5#define CONTAINERLIST_H
6
7#include <span>
8#include <vector>
9#include <atomic>
10#include <mutex>
11
12template <typename T_Container>
14
20template <typename T_Container>
22{
23private:
24 using T_ContainerPtr = T_Container *;
26public:
27 friend struct DynamicContainerListHelper<T_Container>;
28
33 ContainerList(unsigned int expected_max_container)
34 {
35 m_container.emplace_back(expected_max_container); // create expected_max_container containers
36 // and create and populate the container list.
38 m_container.back(),
39 expected_max_container <=1
40 ? std::span<T_ContainerPtr>(&m_singleElementContainerList,1u)
41 : std::span<T_ContainerPtr>(m_containerListHistory.emplace_back(expected_max_container) ));
42 }
43
45 std::size_t size() const { return m_containerList.size(); }
47 T_Container &operator[](unsigned int idx) {
48 assert( idx < m_containerList.size() && m_containerList[idx]);
49 return *(m_containerList[idx]);
50 }
51
52 const T_Container &operator[](unsigned int idx) const {
53 assert( idx < m_containerList.size() && m_containerList[idx]);
54 return *(m_containerList[idx]);
55 }
56
57private:
62 static std::span<T_ContainerPtr> fillContainerList( unsigned int begin_idx,
63 std::vector<T_Container> &container,
64 std::span<T_ContainerPtr> container_list) {
65 unsigned int end_idx=begin_idx+container.size();
66 assert( end_idx <= container_list.size());
67 for (unsigned int idx=begin_idx; idx < end_idx; ++idx) {
68 container_list[idx]=&container[idx-begin_idx];
69 }
70 return container_list;
71 }
72
73
77 std::span<T_ContainerPtr> m_containerList;
78
80 std::vector< std::vector<T_Container> > m_container;
83 std::vector< std::vector<T_ContainerPtr> > m_containerListHistory;
84};
85
87template <typename T_Container>
89 using T_ContainerPtr = T_Container *;
90
92 struct ContainerPtr {
94 protected:
95 ContainerPtr(T_Container *ptr, unsigned int container_idx) : m_container(ptr),m_containerIdx(container_idx) {}
96 public:
97 ContainerPtr(const ContainerPtr &a) = default;
99
102
103 T_Container &operator*() { assert( m_container != nullptr); return *m_container; }
104 const T_Container &operator*() const { assert( m_container != nullptr); return *m_container; }
105 T_Container *operator->() { assert( m_container != nullptr); return m_container; }
106 const T_Container *operator->() const { assert( m_container != nullptr); return m_container; }
107
109 unsigned int containerId() const {
110 return m_containerIdx;
111 }
112
113 private:
114 T_Container *m_container;
115 unsigned int m_containerIdx;
116 };
117
123 void addLargerContainerList(unsigned int container_idx, ContainerList<T_Container> &container_list) {
124 std::lock_guard<std::mutex> container_list_lock(m_containerListMutex);
125 if (container_idx >= container_list.m_containerList.size()) {
126 // create new container list with min_elements extra elements i.e. grow in chunks
127 static constexpr std::size_t min_elments = (sizeof(T_ContainerPtr)>=32u ? 1ul : 64ul/sizeof(T_ContainerPtr)-1);
128 const std::size_t new_size=(m_used+min_elments+1) & (~(min_elments));
129 unsigned int n=new_size - container_list.m_containerList.size();
130 // add a new container_list and add new empty containers
131 container_list.m_container.emplace_back( n );
132 container_list.m_containerListHistory.emplace_back( new_size );
133 std::vector<T_ContainerPtr> &new_container_list = container_list.m_containerListHistory.back();
134 std::vector<T_Container> &extra_container = container_list.m_container.back();
135 assert(new_container_list.size()>=container_list.m_containerList.size());
136 // copy pointers from original container list to new container list
137 std::copy(container_list.m_containerList.begin(),container_list.m_containerList.end(),new_container_list.begin());
138 // set pointers of new container_list
140 extra_container,
141 std::span(new_container_list) );
142 }
143 }
144
148 unsigned int container_idx = m_used++;
149 if (container_idx >= container_list.m_containerList.size()) {
150 addLargerContainerList(container_idx, container_list);
151 }
152 return ContainerPtr(container_list.m_containerList[container_idx],container_idx);
153 }
154
156 std::atomic<unsigned int> m_used{};
157};
158
159#endif
static Double_t a
Helper class which provides a possibly dynamically growing list of containers suitable for a multi-th...
std::vector< std::vector< T_ContainerPtr > > m_containerListHistory
The history of the container lists where each subsequent element is an extended copy of the preceding...
T_Container * T_ContainerPtr
T_ContainerPtr * ContainerPtrList
std::size_t size() const
The number of containers in this list.
std::span< T_ContainerPtr > m_containerList
The current container list.
static std::span< T_ContainerPtr > fillContainerList(unsigned int begin_idx, std::vector< T_Container > &container, std::span< T_ContainerPtr > container_list)
Write pointers to containers in the given vector to a list starting at begin_index.
ContainerList(unsigned int expected_max_container)
Create a container list for a certain number of containers.
T_Container & operator[](unsigned int idx)
Return the container with the given container index (read-write).a.
const T_Container & operator[](unsigned int idx) const
Return the container with the given container index (read-only).
std::vector< std::vector< T_Container > > m_container
All containers.
T_Container * m_singleElementContainerList
A container "list" which can only contain a single container.
Helper which provides a pointer to a container and the index of the container in the container list.
ContainerPtr(ContainerPtr &&a)=default
ContainerPtr(const ContainerPtr &a)=default
const T_Container * operator->() const
ContainerPtr(T_Container *ptr, unsigned int container_idx)
ContainerPtr & operator=(ContainerPtr &&a)=default
unsigned int containerId() const
Get the index of container in the container list.
const T_Container & operator*() const
ContainerPtr & operator=(const ContainerPtr &a)=default
Helper class which allows to dynamically grow the container list.
std::atomic< unsigned int > m_used
void addLargerContainerList(unsigned int container_idx, ContainerList< T_Container > &container_list)
If the specified entry does not exist in the container list create an extended copy which contains th...
ContainerPtr getNewContainer(ContainerList< T_Container > &container_list)
Get an unused container from the given container list.