ATLAS Offline Software
ConcurrentBitset.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3 */
13 
14 
15 namespace CxxUtils {
16 
17 
18 //*********************************************************************************
19 // Constructors, destructors, assignment.
20 
21 
27  : m_impl (new (nbits) Impl (nbits))
28 {
29 }
30 
31 
40  : m_impl (new ((*other.m_impl).nbits()) Impl ((*other.m_impl)))
41 {
42 }
43 
44 
56 ConcurrentBitset::ConcurrentBitset (std::initializer_list<bit_t> l,
57  bit_t nbits /*= 0*/)
58 {
59  if (nbits == 0) {
60  // Set the size of the set based on the maximum value in the list.
61  auto max_it = std::max_element (l.begin(), l.end());
62  if (max_it != l.end()) {
63  nbits = *max_it + 1;
64  }
65  // Round up.
66  nbits = (nbits + BLOCKSIZE-1) & ~MASK;
67  }
68  m_impl = new (nbits) Impl (nbits);
69  for (bit_t b : l) {
70  set (b);
71  }
72 }
73 
74 
83 {
84  other.emptyGarbage();
85  Impl* impl = other.m_impl;
86  other.m_impl = nullptr;
87  m_impl = impl;
88 }
89 
90 
95 {
96  delete m_impl;
97  emptyGarbage();
98 }
99 
100 
109 {
110  if (this != &other) {
111  const Impl* otherImpl = other.m_impl;
112  expand (otherImpl->nbits());
113  (*m_impl).assign (*otherImpl);
114  }
115  return *this;
116 }
117 
118 
127 {
128  if (this != &other) {
129  emptyGarbage();
130  other.emptyGarbage();
131  delete m_impl;
132  Impl* impl = other.m_impl;
133  other.m_impl = nullptr;
134  m_impl = impl;
135  }
136  return *this;
137 }
138 
139 
149 {
150  lock_t lock (m_mutex);
151  for (Impl* p : m_garbage) {
152  free (p);
153  }
154  m_garbage.clear();
155 }
156 
157 
163 {
164  // Need to take out the lock.
165  lock_t lock (m_mutex);
166  // Check the size again while we're holding the lock.
167  bit_t nbits = (*m_impl).nbits();
168  if (new_nbits > nbits) {
169  // We need to expand. Allocate a new implementation and initialize it,
170  // copying from the existing implementation.
171  Impl* i = new (new_nbits) Impl (*m_impl, new_nbits);
172 
173  // Remember that we need to delete the old object.
174  m_garbage.push_back (m_impl);
175 
176  // Publish the new one.
177  m_impl = i;
178  }
179 }
180 
181 
182 //*********************************************************************************
183 // Implementation.
184 
185 
186 // Use popcnt instruction if available. This ugliness needed
187 // because our default compilation options do not enable
188 // use of this instruction.
189 #if defined(__x86_64__) && HAVE_FUNCTION_MULTIVERSIONING
190 
193 __attribute__ ((target ("popcnt")))
194 ConcurrentBitset::bit_t
195 ConcurrentBitset::Impl::count() const
196 {
197  bit_t n = 0;
198  for (bit_t i=0; i<m_nblocks; i++) {
200  }
201  return n;
202 }
206 __attribute__ ((target ("default")))
207 #endif
210 {
211  bit_t n = 0;
212  for (bit_t i=0; i<m_nblocks; i++) {
214  }
215  return n;
216 }
217 
218 
223 {
224  for (bit_t i = 0; i < m_nblocks; i++) {
225  if (m_data[i]) return false;
226  }
227  return true;
228 }
229 
230 
235 {
236  if (m_nblocks == 0) {
237  return true;
238  }
239 
240  // Check all blocks except the last.
241  for (bit_t i = 0; i < m_nblocks-1; i++) {
242  if (m_data[i] != ~static_cast<Block_t>(0)) return false;
243  }
244  // Special case for the last, since the last block may not be full.
245  if (m_data[m_nblocks] != ones<Block_t> (m_nbits - (m_nblocks-1)*BLOCKSIZE)) {
246  return false;
247  }
248  return true;
249 }
250 
251 
259 {
260  for (bit_t i=0; i<m_nblocks; i++) {
261  m_data[i].store (~static_cast<Block_t>(0), std::memory_order_relaxed);
262  }
263  std::atomic_thread_fence (std::memory_order_seq_cst);
264  if (m_nblocks > 0) {
265  m_hwm = m_nblocks-1;
266  }
267 }
268 
269 
277 {
278  for (bit_t i=0; i<m_nblocks; i++) {
279  m_data[i] ^= ~static_cast<Block_t>(0);
280  }
281  if (m_nblocks > 0) {
282  m_hwm = m_nblocks-1;
283  }
284 }
285 
286 
287 } // namespace CxxUtils
CxxUtils::ConcurrentBitset::Impl::m_nblocks
size_t m_nblocks
Number of blocks in the container.
Definition: ConcurrentBitset.h:1051
python.PerfMonSerializer.p
def p
Definition: PerfMonSerializer.py:743
ConcurrentBitset.h
Variable-sized bitset allowing (mostly) concurrent access.
CxxUtils::ConcurrentBitset::Impl::count
bit_t count() const
Definition: ConcurrentBitset.cxx:209
CxxUtils::ConcurrentBitset
Variable-sized bitset allowing (mostly) concurrent access.
Definition: ConcurrentBitset.h:146
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:149
CSV_InDetExporter.new
new
Definition: CSV_InDetExporter.py:145
CxxUtils::ConcurrentBitset::bit_t
size_t bit_t
A bit number.
Definition: ConcurrentBitset.h:164
CxxUtils::ConcurrentBitset::Impl::all
bool all() const
Return true if all bits in the set are 1.
Definition: ConcurrentBitset.cxx:234
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
CxxUtils::ConcurrentBitset::Impl::flip
void flip()
Flip the state of all bits in the set.
Definition: ConcurrentBitset.cxx:276
CxxUtils::ConcurrentBitset::m_impl
std::atomic< Impl * > m_impl
The current implementation object.
Definition: ConcurrentBitset.h:1068
CxxUtils::ConcurrentBitset::ConcurrentBitset
ConcurrentBitset(bit_t nbits=0)
Constructor.
Definition: ConcurrentBitset.cxx:26
XMLtoHeader.count
count
Definition: XMLtoHeader.py:85
CxxUtils::ConcurrentBitset::expandOol
void expandOol(bit_t new_nbits)
Expand the container: out-of-line portion.
Definition: ConcurrentBitset.cxx:162
CxxUtils::ConcurrentBitset::lock_t
std::lock_guard< mutex_t > lock_t
Definition: ConcurrentBitset.h:1075
CxxUtils::ConcurrentBitset::Impl::none
bool none() const
Return true if there are no 1 bits in the set.
Definition: ConcurrentBitset.cxx:222
CxxUtils::ConcurrentBitset::Impl
Implementation object.
Definition: ConcurrentBitset.h:846
CxxUtils::ConcurrentBitset::Impl::set
void set()
Turn on all bits in the set.
Definition: ConcurrentBitset.cxx:258
lumiFormat.i
int i
Definition: lumiFormat.py:92
CxxUtils::ConcurrentBitset::Impl::m_data
std::atomic< Block_t > m_data[1]
The set data.
Definition: ConcurrentBitset.h:1059
beamspotman.n
n
Definition: beamspotman.py:731
CxxUtils
Definition: aligned_vector.h:29
findIdxOfMinimum::Impl
Impl
Definition: GSFFindIndexOfMinimum.h:350
CxxUtils::count_ones
constexpr unsigned count_ones(unsigned x)
Count number of set bits.
Definition: bitscan.h:141
CxxUtils::ConcurrentBitset::MASK
static const size_t MASK
Mask to select out the bit offset within one Block_t.
Definition: ConcurrentBitset.h:161
CxxUtils::ConcurrentBitset::~ConcurrentBitset
~ConcurrentBitset()
Destructor.
Definition: ConcurrentBitset.cxx:94
CxxUtils::ConcurrentBitset::BLOCKSIZE
static const size_t BLOCKSIZE
Size, in bits, of Block_t.
Definition: ConcurrentBitset.h:158
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
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.
findIdxOfMinimum::impl
ATH_ALWAYS_INLINE int32_t impl(const float *distancesIn, int n)
Definition: GSFFindIndexOfMinimum.h:359
CxxUtils::ConcurrentBitset::m_garbage
std::vector< Impl * > m_garbage
Old implementation objects, pending deletion.
Definition: ConcurrentBitset.h:1071
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:1076
__attribute__
__attribute__((always_inline)) inline uint16_t TileCalibDrawerBase
Definition: TileCalibDrawerBase.h:190
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
CxxUtils::ConcurrentBitset::operator=
ConcurrentBitset & operator=(const ConcurrentBitset &other)
Assignment.
Definition: ConcurrentBitset.cxx:108
COOLRates.target
target
Definition: COOLRates.py:1106
CxxUtils::ConcurrentBitset::emptyGarbage
void emptyGarbage()
Clean up old versions of the set.
Definition: ConcurrentBitset.cxx:148