ATLAS Offline Software
ConcurrentBitset.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3 */
13 #include <bit>
14 
15 
16 namespace CxxUtils {
17 
18 
19 //*********************************************************************************
20 // Constructors, destructors, assignment.
21 
22 
28  : m_impl (new (nbits) Impl (nbits))
29 {
30 }
31 
32 
41 {
42  // Be careful: don't read other.m_impl more than once. It may change
43  // at any time.
44  const Impl* otherImpl = other.m_impl;
45  // cppcheck-suppress useInitializationList
46  m_impl = new (otherImpl->nbits()) Impl (*otherImpl);
47 }
48 
49 
61 ConcurrentBitset::ConcurrentBitset (std::initializer_list<bit_t> l,
62  bit_t nbits /*= 0*/)
63 {
64  if (nbits == 0) {
65  // Set the size of the set based on the maximum value in the list.
66  auto max_it = std::max_element (l.begin(), l.end());
67  if (max_it != l.end()) {
68  nbits = *max_it + 1;
69  }
70  // Round up.
71  nbits = (nbits + BLOCKSIZE-1) & ~MASK;
72  }
73  m_impl = new (nbits) Impl (nbits);
74  for (bit_t b : l) {
75  set (b);
76  }
77 }
78 
79 
88 {
89  other.emptyGarbage();
90  Impl* impl = other.m_impl;
91  other.m_impl = nullptr;
92  m_impl = impl;
93 }
94 
95 
100 {
101  delete m_impl;
102  emptyGarbage();
103 }
104 
105 
114 {
115  if (this != &other) {
116  const Impl* otherImpl = other.m_impl;
117  expand (otherImpl->nbits());
118  (*m_impl).assign (*otherImpl);
119  }
120  return *this;
121 }
122 
123 
132 {
133  if (this != &other) {
134  emptyGarbage();
135  other.emptyGarbage();
136  delete m_impl;
137  Impl* impl = other.m_impl;
138  other.m_impl = nullptr;
139  m_impl = impl;
140  }
141  return *this;
142 }
143 
144 
154 {
155  lock_t lock (m_mutex);
156  for (Impl* p : m_garbage) {
157  free (p);
158  }
159  m_garbage.clear();
160 }
161 
162 
168 {
169  // Need to take out the lock.
170  lock_t lock (m_mutex);
171  // Check the size again while we're holding the lock.
172  bit_t nbits = (*m_impl).nbits();
173  if (new_nbits > nbits) {
174  // We need to expand. Allocate a new implementation and initialize it,
175  // copying from the existing implementation.
176  Impl* i = new (new_nbits) Impl (*m_impl, new_nbits);
177 
178  // Remember that we need to delete the old object.
179  m_garbage.push_back (m_impl);
180 
181  // Publish the new one.
182  m_impl = i;
183  }
184 }
185 
186 
187 //*********************************************************************************
188 // Implementation.
189 
190 
196 {
197  bit_t n = 0;
198  for (bit_t i=0; i<m_nblocks; i++) {
199  n += std::popcount (m_data[i].load());
200  }
201  return n;
202 }
203 
204 
209 {
210  for (bit_t i = 0; i < m_nblocks; i++) {
211  if (m_data[i]) return false;
212  }
213  return true;
214 }
215 
216 
221 {
222  if (m_nblocks == 0) {
223  return true;
224  }
225 
226  // Check all blocks except the last.
227  for (bit_t i = 0; i < m_nblocks-1; i++) {
228  if (m_data[i] != ~static_cast<Block_t>(0)) return false;
229  }
230  // Special case for the last, since the last block may not be full.
231  if (m_data[m_nblocks] != ones<Block_t> (m_nbits - (m_nblocks-1)*BLOCKSIZE)) {
232  return false;
233  }
234  return true;
235 }
236 
237 
245 {
246  for (bit_t i=0; i<m_nblocks; i++) {
247  m_data[i].store (~static_cast<Block_t>(0), std::memory_order_relaxed);
248  }
249  std::atomic_thread_fence (std::memory_order_seq_cst);
250  if (m_nblocks > 0) {
251  m_hwm = m_nblocks-1;
252  }
253 }
254 
255 
263 {
264  for (bit_t i=0; i<m_nblocks; i++) {
265  m_data[i] ^= ~static_cast<Block_t>(0);
266  }
267  if (m_nblocks > 0) {
268  m_hwm = m_nblocks-1;
269  }
270 }
271 
272 
273 } // namespace CxxUtils
CxxUtils::ConcurrentBitset::Impl::m_nblocks
size_t m_nblocks
Number of blocks in the container.
Definition: ConcurrentBitset.h:1039
ConcurrentBitset.h
Variable-sized bitset allowing (mostly) concurrent access.
CxxUtils::ConcurrentBitset::Impl::count
bit_t count() const
Count the number of 1 bits in the set.
Definition: ConcurrentBitset.cxx:195
CxxUtils::ConcurrentBitset
Variable-sized bitset allowing (mostly) concurrent access.
Definition: ConcurrentBitset.h:145
m_data
std::vector< T > m_data
Definition: TrackTruthMatchingBaseAlg.cxx:660
CxxUtils::ConcurrentBitset::Block_t
unsigned long Block_t
Internal type used to hold the bitset data.
Definition: ConcurrentBitset.h:148
CSV_InDetExporter.new
new
Definition: CSV_InDetExporter.py:145
CxxUtils::ConcurrentBitset::bit_t
size_t bit_t
A bit number.
Definition: ConcurrentBitset.h:163
CxxUtils::ConcurrentBitset::Impl::all
bool all() const
Return true if all bits in the set are 1.
Definition: ConcurrentBitset.cxx:220
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:157
python.RatesEmulationExample.lock
lock
Definition: RatesEmulationExample.py:148
CxxUtils::ConcurrentBitset::Impl::flip
void flip()
Flip the state of all bits in the set.
Definition: ConcurrentBitset.cxx:262
CxxUtils::ConcurrentBitset::m_impl
std::atomic< Impl * > m_impl
The current implementation object.
Definition: ConcurrentBitset.h:1056
CxxUtils::ConcurrentBitset::ConcurrentBitset
ConcurrentBitset(bit_t nbits=0)
Constructor.
Definition: ConcurrentBitset.cxx:27
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:209
CxxUtils::ConcurrentBitset::expandOol
void expandOol(bit_t new_nbits)
Expand the container: out-of-line portion.
Definition: ConcurrentBitset.cxx:167
CxxUtils::ConcurrentBitset::lock_t
std::lock_guard< mutex_t > lock_t
Definition: ConcurrentBitset.h:1063
CxxUtils::ConcurrentBitset::Impl::none
bool none() const
Return true if there are no 1 bits in the set.
Definition: ConcurrentBitset.cxx:208
CxxUtils::ConcurrentBitset::Impl
Implementation object.
Definition: ConcurrentBitset.h:845
CxxUtils::ConcurrentBitset::Impl::set
void set()
Turn on all bits in the set.
Definition: ConcurrentBitset.cxx:244
lumiFormat.i
int i
Definition: lumiFormat.py:85
CxxUtils::ConcurrentBitset::Impl::m_data
std::atomic< Block_t > m_data[1]
The set data.
Definition: ConcurrentBitset.h:1047
beamspotman.n
n
Definition: beamspotman.py:729
CxxUtils
Definition: aligned_vector.h:29
CxxUtils::ConcurrentBitset::MASK
static const size_t MASK
Mask to select out the bit offset within one Block_t.
Definition: ConcurrentBitset.h:160
CxxUtils::ConcurrentBitset::~ConcurrentBitset
~ConcurrentBitset()
Destructor.
Definition: ConcurrentBitset.cxx:99
CxxUtils::ConcurrentBitset::BLOCKSIZE
static const size_t BLOCKSIZE
Size, in bits, of Block_t.
Definition: ConcurrentBitset.h:157
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:76
CxxUtils::ConcurrentBitset::expand
void expand(bit_t new_nbits)
Expand the container.
CxxUtils::ConcurrentBitset::Impl::nbits
bit_t nbits() const
Return the number of bits in the set.
CxxUtils::ConcurrentBitset::m_garbage
std::vector< Impl * > m_garbage
Old implementation objects, pending deletion.
Definition: ConcurrentBitset.h:1059
CxxUtils::ConcurrentBitset::set
ConcurrentBitset & set()
Turn on all bits in the set.
impl
Definition: CaloGPUClusterAndCellDataMonitorOptions.h:46
CxxUtils::ConcurrentBitset::m_mutex
mutex_t m_mutex
Definition: ConcurrentBitset.h:1064
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
CxxUtils::ConcurrentBitset::operator=
ConcurrentBitset & operator=(const ConcurrentBitset &other)
Assignment.
Definition: ConcurrentBitset.cxx:113
python.root_pickle.load
def load(f, use_proxy=1, key=None)
Definition: root_pickle.py:476
CxxUtils::ConcurrentBitset::emptyGarbage
void emptyGarbage()
Clean up old versions of the set.
Definition: ConcurrentBitset.cxx:153