ATLAS Offline Software
ConcurrentBitset.h
Go to the documentation of this file.
1 // This file's extension implies that it's C, but it's really -*- C++ -*-.
2 /*
3  Copyright (C) 2002-2020 CERN for the benefit of the ATLAS collaboration
4 */
5 /*
6  */
7 // $Id$
16 #ifndef CXXUTILS_CONCURRENTBITSET_H
17 #define CXXUTILS_CONCURRENTBITSET_H
18 
19 
21 #include "CxxUtils/features.h"
22 #include "CxxUtils/bitscan.h"
23 #include "CxxUtils/ones.h"
24 #include <climits>
25 #include <vector>
26 #include <algorithm>
27 #include <iterator>
28 #include <atomic>
29 #include <mutex>
30 #include <memory>
31 #include <type_traits>
32 #include <cstddef>
33 
34 
35 namespace CxxUtils {
36 
37 
146 {
147 private:
148  // Forward declaration of implementation class.
149  class Impl;
150 
155  typedef unsigned long Block_t;
156 
158  static const size_t BLOCKSIZE = sizeof(Block_t) * CHAR_BIT;
159 
161  static const size_t MASK = BLOCKSIZE-1;
162 
163 
164  static_assert (std::atomic<Block_t>::is_always_lock_free);
165 
166 public:
168  typedef size_t bit_t;
169 
170 
171  //========================================================================
174 
175 
180  ConcurrentBitset (bit_t nbits = 0);
181 
182 
191 
192 
204  ConcurrentBitset (std::initializer_list<bit_t> l, bit_t nbits = 0);
205 
206 
215 
216 
221 
222 
231 
232 
241 
242 
251  void emptyGarbage();
252 
253 
255  //========================================================================
258 
259 
263  bit_t capacity() const;
264 
265 
269  bit_t count() const;
270 
271 
280  bit_t size() const;
281 
282 
290  bool test (bit_t bit) const;
291 
292 
300  size_t count (bit_t bit) const;
301 
302 
306  bool empty() const;
307 
308 
312  bool none() const;
313 
314 
318  bool all() const;
319 
320 
324  bool any() const;
325 
326 
328  //========================================================================
331 
332 
340 
341 
349 
350 
358 
359 
367 
368 
377 
378 
380  //========================================================================
383 
384 
392 
393 
401 
402 
410 
411 
419 
420 
429 
430 
439 
440 
449 
450 
461 
462 
467 
468 
470  //========================================================================
473 
474 
479  bool operator== (const ConcurrentBitset& other) const;
480 
481 
486  bool operator!= (const ConcurrentBitset& other) const;
487 
488 
490  //========================================================================
493 
494 
506  ConcurrentBitset& insert (bit_t bit, bit_t new_nbits = 0);
507 
508 
529  // The enable_if is needed to keep this something like
530  // bs.insert (1, 2)
531  // from matching this overload.
532  template <class ITERATOR,
533  typename = typename std::enable_if<
534  std::is_base_of<
535  typename std::forward_iterator_tag,
536  typename std::iterator_traits<ITERATOR>::iterator_category
537  >::value> >
538  ConcurrentBitset& insert (ITERATOR beg, ITERATOR end, bit_t new_nbits = 0);
539 
540 
558  ConcurrentBitset& insert (std::initializer_list<bit_t> l, bit_t new_nbits = 0);
559 
560 
572 
573 
575  //========================================================================
578 
579 
585  class reference
586  {
587  private:
588  friend class ConcurrentBitset;
589 
590 
597 
598 
599  public:
604  reference& operator= (bool val) noexcept;
605 
606 
618  reference& operator= (const reference& r) noexcept;
619 
620 
624  operator bool() const noexcept;
625 
626 
630  bool operator~() const noexcept;
631 
632 
636  reference& flip() noexcept;
637 
638 
639  private:
641  std::atomic<Block_t>* m_block;
642 
645  };
646 
647 
652  bool operator[] (bit_t bit) const;
653 
654 
662  reference operator[] (bit_t bit);
663 
664 
666  //========================================================================
669 
670 
695  {
696  typedef std::forward_iterator_tag iterator_category;
697  typedef size_t value_type;
698  typedef ptrdiff_t difference_type;
699  typedef const value_type* pointer;
700  typedef const value_type& reference;
701 
702 
703  private:
705 
706 
716  bit_t bit,
717  const std::atomic<Block_t>* data,
718  const std::atomic<Block_t>* end);
719 
720 
721  public:
725  bit_t operator*() const;
726 
727 
732 
733 
738 
739 
744  bool operator== (const const_iterator& other) const;
745 
746 
751  bool operator!= (const const_iterator& other) const;
752 
753 
754  private:
759 
762 
764  const std::atomic<Block_t>* m_data;
765 
766 
768  const std::atomic<Block_t>* m_end;
769  };
770 
771 
776 
777 
782 
783 
789  const_iterator find (bit_t bit) const;
790 
791 
792 
794 private:
795  //========================================================================
798 
799 
804  static bit_t nBlocks (bit_t nbits);
805 
806 
814  Impl* newImpl (bit_t nbits);
815 
816 
821  void expand (bit_t new_nbits);
822 
823 
828  void expandOol (bit_t new_nbits);
829 
830 
845  class Impl
846  {
847  public:
853  void* operator new (size_t /*sz*/, bit_t nbits);
854 
855 
856  /*
857  * @brief Free an Impl structure.
858  * @param p Pointer to the object to free.
859  */
860  void operator delete (void* p);
861 
862 
867  Impl (bit_t nbits);
868 
869 
878  Impl (const Impl& other, bit_t nbits = 0);
879 
880 
881  // Assignment is unimplemented.
882  Impl& operator= (const Impl&) = delete;
883 
884 
894  void assign (const Impl& other);
895 
896 
900  bit_t nbits() const;
901 
902 
910  bool test (bit_t bit) const;
911 
912 
913  // Use popcnt instruction if available. This ugliness needed
914  // because our default compilation options do not enable
915  // use of this instruction.
916 #if defined(__x86_64__) && HAVE_FUNCTION_MULTIVERSIONING
917 
920  __attribute__ ((target ("popcnt")))
921  bit_t count() const;
925  __attribute__ ((target ("default")))
926 #endif
927  bit_t count() const;
928 
929 
933  bool none() const;
934 
935 
939  bool all() const;
940 
941 
948  std::atomic<Block_t>* block (bit_t bit);
949 
950 
957  void set (bit_t bit);
958 
959 
966  void reset (bit_t bit);
967 
968 
975  void flip (bit_t bit);
976 
977 
984  void clear();
985 
986 
993  void set();
994 
995 
1002  void flip();
1003 
1004 
1005  typedef void operator_t (std::atomic<Block_t>& a, Block_t v);
1015  void operate (operator_t op, const Impl& other);
1016 
1017 
1022  bool operator== (const Impl& other) const;
1023 
1024 
1025 
1030 
1031 
1036 
1037 
1044 
1045 
1046  private:
1048  size_t m_nbits;
1049 
1051  size_t m_nblocks;
1052 
1054  std::atomic<size_t> m_hwm;
1055 
1059  std::atomic<Block_t> m_data[1];
1060  };
1061 
1062 
1064 
1065 
1066 private:
1068  std::atomic<Impl*> m_impl;
1069 
1071  std::vector<Impl*> m_garbage;
1072 
1075  typedef std::lock_guard<mutex_t> lock_t;
1077 };
1078 
1079 
1080 } // namespace CxxUtils
1081 
1082 
1084 
1085 
1086 #endif // not CXXUTILS_CONCURRENTBITSET_H
CxxUtils::ConcurrentBitset::set
ConcurrentBitset & set(bit_t bit)
Turn on one bit.
beamspotman.r
def r
Definition: beamspotman.py:676
data
char data[hepevt_bytes_allocation_ATLAS]
Definition: HepEvt.cxx:11
CxxUtils::ConcurrentBitset::const_iterator::value_type
size_t value_type
Definition: ConcurrentBitset.h:697
features.h
Some additional feature test macros.
CxxUtils::ConcurrentBitset::count
size_t count(bit_t bit) const
Test to see if a bit is set.
CxxUtils::ConcurrentBitset::Impl::m_nblocks
size_t m_nblocks
Number of blocks in the container.
Definition: ConcurrentBitset.h:1051
CxxUtils::ConcurrentBitset::mutex_t
std::mutex mutex_t
Mutex used for synchronization when switching to a new implementation object.
Definition: ConcurrentBitset.h:1074
CxxUtils::ConcurrentBitset::flip
ConcurrentBitset & flip(bit_t bit)
Flip the value of one bit.
CxxUtils::ConcurrentBitset::const_iterator::difference_type
ptrdiff_t difference_type
Definition: ConcurrentBitset.h:698
CxxUtils::ConcurrentBitset::const_iterator::pointer
const value_type * pointer
Definition: ConcurrentBitset.h:699
CxxUtils::ConcurrentBitset::all
bool all() const
Return true if all bits in the set are 1.
CxxUtils::ConcurrentBitset::count
bit_t count() const
Count the number of 1 bits in the set.
CxxUtils::ConcurrentBitset::Impl::clear
void clear()
Clear all bits in the set.
CxxUtils::ConcurrentBitset
Variable-sized bitset allowing (mostly) concurrent access.
Definition: ConcurrentBitset.h:146
CxxUtils::ConcurrentBitset::const_iterator::operator++
const_iterator & operator++()
Advance the iterator to the next set bit (preincrement).
CxxUtils::ConcurrentBitset::Impl::block
std::atomic< Block_t > * block(bit_t bit)
Return a pointer to the block containing bit.
BeamSpot::mutex
std::mutex mutex
Definition: InDetBeamSpotVertex.cxx:18
m_data
std::vector< T > m_data
Definition: TrackTruthMatchingBaseAlg.cxx:660
CxxUtils::ConcurrentBitset::const_iterator::operator++
const_iterator operator++(int)
Advance the iterator to the next set bit (postincrement).
CxxUtils::ConcurrentBitset::Block_t
unsigned long Block_t
Internal type used to hold the bitset data.
Definition: ConcurrentBitset.h:149
CxxUtils::ConcurrentBitset::end
const_iterator end() const
Return an end iterator.
CxxUtils::ConcurrentBitset::capacity
bit_t capacity() const
The number of bits that this container can hold.
CxxUtils::ConcurrentBitset::bit_t
size_t bit_t
A bit number.
Definition: ConcurrentBitset.h:164
CxxUtils::ConcurrentBitset::operator&=
ConcurrentBitset & operator&=(const ConcurrentBitset &other)
AND this set with another set.
CxxUtils::ConcurrentBitset::operator~
ConcurrentBitset operator~() const
Return a new set that is the complement of this set.
CxxUtils::ConcurrentBitset::operator^=
ConcurrentBitset & operator^=(const ConcurrentBitset &other)
XOR this set with another set.
CxxUtils::ConcurrentBitset::const_iterator
Iterator over all 1 bits in the set.
Definition: ConcurrentBitset.h:695
CxxUtils::ConcurrentBitset::reference::m_mask
Block_t m_mask
Mask of the referenced bit within the block.
Definition: ConcurrentBitset.h:644
athena.value
value
Definition: athena.py:124
UploadAMITag.l
list l
Definition: UploadAMITag.larcaf.py:158
CxxUtils::ConcurrentBitset::const_iterator::const_iterator
const_iterator(Block_t cache, bit_t bit, const std::atomic< Block_t > *data, const std::atomic< Block_t > *end)
Constructor.
CxxUtils::ConcurrentBitset::Impl::operate
void operate(operator_t op, const Impl &other)
Apply a binary operation.
CxxUtils::ConcurrentBitset::m_impl
std::atomic< Impl * > m_impl
The current implementation object.
Definition: ConcurrentBitset.h:1068
const
bool const RAWDATA *ch2 const
Definition: LArRodBlockPhysicsV0.cxx:560
CxxUtils::ConcurrentBitset::Impl::find
const_iterator find(bit_t bit) const
If bit bit is set, return an iterator pointing to it.
ConcurrentBitset.icc
CxxUtils::ConcurrentBitset::reset
ConcurrentBitset & reset()
Clear all bits in the set.
CxxUtils::ConcurrentBitset::const_iterator::reference
const value_type & reference
Definition: ConcurrentBitset.h:700
atomic_fetch_minmax.h
Atomic min/max functions.
CxxUtils::ConcurrentBitset::insert
ConcurrentBitset & insert(ITERATOR beg, ITERATOR end, bit_t new_nbits=0)
Set several bits to 1.
CxxUtils::ConcurrentBitset::Impl::set
void set(bit_t bit)
Turn on one bit.
CxxUtils::ConcurrentBitset::clear
ConcurrentBitset & clear()
Clear all bits in the set.
CxxUtils::ConcurrentBitset::ConcurrentBitset
ConcurrentBitset(bit_t nbits=0)
Constructor.
Definition: ConcurrentBitset.cxx:26
CxxUtils::ConcurrentBitset::Impl::Impl
Impl(const Impl &other, bit_t nbits=0)
Copy constructor.
CxxUtils::ConcurrentBitset::operator-=
ConcurrentBitset & operator-=(const ConcurrentBitset &other)
Subtract another set from this set.
CxxUtils::ConcurrentBitset::reference::reference
reference(Impl &impl, bit_t bit)
Constructor.
CxxUtils::ConcurrentBitset::const_iterator::iterator_category
std::forward_iterator_tag iterator_category
Definition: ConcurrentBitset.h:696
CxxUtils::ConcurrentBitset::operator|=
ConcurrentBitset & operator|=(const ConcurrentBitset &other)
OR this set with another set.
CxxUtils::ConcurrentBitset::reference
A reference to one bit in a set.
Definition: ConcurrentBitset.h:586
python.utils.AtlRunQueryDQUtils.p
p
Definition: AtlRunQueryDQUtils.py:210
CxxUtils::ConcurrentBitset::expandOol
void expandOol(bit_t new_nbits)
Expand the container: out-of-line portion.
Definition: ConcurrentBitset.cxx:162
CxxUtils::ConcurrentBitset::size
bit_t size() const
Count the number of 1 bits in the set.
CxxUtils::ConcurrentBitset::lock_t
std::lock_guard< mutex_t > lock_t
Definition: ConcurrentBitset.h:1075
CxxUtils::ConcurrentBitset::insert
ConcurrentBitset & insert(std::initializer_list< bit_t > l, bit_t new_nbits=0)
Set several bits to 1.
CxxUtils::ConcurrentBitset::Impl
Implementation object.
Definition: ConcurrentBitset.h:846
CxxUtils::ConcurrentBitset::reference::operator=
reference & operator=(bool val) noexcept
Set the referenced bit to a given value.
CxxUtils::ConcurrentBitset::reference::m_block
std::atomic< Block_t > * m_block
Pointer to the block containing the referenced bit.
Definition: ConcurrentBitset.h:641
CxxUtils::ConcurrentBitset::insert
ConcurrentBitset & insert(bit_t bit, bit_t new_nbits=0)
Set a bit to 1.
CxxUtils::ConcurrentBitset::Impl::begin
const_iterator begin() const
Return an iterator referencing the first 1 bit.
CxxUtils::ConcurrentBitset::operator!=
bool operator!=(const ConcurrentBitset &other) const
Test two sets for inequality.
CxxUtils::ConcurrentBitset::reset
ConcurrentBitset & reset(bit_t bit)
Turn off one bit.
CxxUtils
Definition: aligned_vector.h:29
CxxUtils::ConcurrentBitset::Impl::end
const_iterator end() const
Return the end iterator.
CxxUtils::ConcurrentBitset::empty
bool empty() const
Return true if there are no 1 bits in the set.
CxxUtils::ConcurrentBitset::MASK
static const size_t MASK
Mask to select out the bit offset within one Block_t.
Definition: ConcurrentBitset.h:161
ones.h
Construct a bit mask.
CxxUtils::ConcurrentBitset::Impl::m_nbits
size_t m_nbits
Number of bits in the container.
Definition: ConcurrentBitset.h:1048
CxxUtils::ConcurrentBitset::~ConcurrentBitset
~ConcurrentBitset()
Destructor.
Definition: ConcurrentBitset.cxx:94
CxxUtils::ConcurrentBitset::set
ConcurrentBitset & set(bit_t bit, bool val)
Set the value of one bit.
CxxUtils::ConcurrentBitset::find
const_iterator find(bit_t bit) const
If bit bit is set, return an iterator pointing to it.
CxxUtils::ConcurrentBitset::any
bool any() const
Return true if there are any 1 bits in the set.
CxxUtils::ConcurrentBitset::insert
ConcurrentBitset & insert(const ConcurrentBitset &other)
Turn on bits listed in another set.
CxxUtils::ConcurrentBitset::Impl::assign
void assign(const Impl &other)
Copy from another instance.
CxxUtils::ConcurrentBitset::begin
const_iterator begin() const
Return a begin iterator.
CxxUtils::ConcurrentBitset::Impl::reset
void reset(bit_t bit)
Turn off one bit.
CxxUtils::ConcurrentBitset::BLOCKSIZE
static const size_t BLOCKSIZE
Size, in bits, of Block_t.
Definition: ConcurrentBitset.h:158
CxxUtils::ConcurrentBitset::const_iterator::m_data
const std::atomic< Block_t > * m_data
Pointer to the block containing the bit which we're currently referencing.
Definition: ConcurrentBitset.h:764
CxxUtils::ConcurrentBitset::const_iterator::m_end
const std::atomic< Block_t > * m_end
Pointer to one past the last block in the set.
Definition: ConcurrentBitset.h:768
WriteBchToCool.beg
beg
Definition: WriteBchToCool.py:69
CxxUtils::ConcurrentBitset::none
bool none() const
Return true if there are no 1 bits in the set.
private
#define private
Definition: DetDescrConditionsDict_dict_fixes.cxx:13
CxxUtils::ConcurrentBitset::Impl::m_hwm
std::atomic< size_t > m_hwm
High-water mark: index of last block with a 1 bit.
Definition: ConcurrentBitset.h:1054
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:1071
CxxUtils::ConcurrentBitset::const_iterator::m_bit
bit_t m_bit
Bit number which we're currently referencing.
Definition: ConcurrentBitset.h:761
CxxUtils::ConcurrentBitset::Impl::test
bool test(bit_t bit) const
Test to see if a bit is set.
CxxUtils::ConcurrentBitset::set
ConcurrentBitset & set()
Turn on all bits in the set.
CxxUtils::ConcurrentBitset::flip
ConcurrentBitset & flip()
Flip the state of all bits in the set.
python.PyAthena.v
v
Definition: PyAthena.py:154
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
CxxUtils::ConcurrentBitset::Impl::flip
void flip(bit_t bit)
Flip the value of one bit.
a
TList * a
Definition: liststreamerinfos.cxx:10
InDetDD::other
@ other
Definition: InDetDD_Defs.h:16
copySelective.target
string target
Definition: copySelective.py:37
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
CxxUtils::ConcurrentBitset::operator=
ConcurrentBitset & operator=(const ConcurrentBitset &other)
Assignment.
Definition: ConcurrentBitset.cxx:108
CxxUtils::ConcurrentBitset::Impl::operator_t
void operator_t(std::atomic< Block_t > &a, Block_t v)
Definition: ConcurrentBitset.h:1005
CxxUtils::ConcurrentBitset::newImpl
Impl * newImpl(bit_t nbits)
Create a new, uninitialized implementation object.
CxxUtils::ConcurrentBitset::const_iterator::m_cache
Block_t m_cache
Cache of the block to which we're currently pointing.
Definition: ConcurrentBitset.h:758
python.CaloScaleNoiseConfig.default
default
Definition: CaloScaleNoiseConfig.py:79
CxxUtils::ConcurrentBitset::emptyGarbage
void emptyGarbage()
Clean up old versions of the set.
Definition: ConcurrentBitset.cxx:148
CxxUtils::ConcurrentBitset::operator==
bool operator==(const ConcurrentBitset &other) const
Test two sets for equality.
CxxUtils::ConcurrentBitset::erase
ConcurrentBitset & erase(bit_t bit)
Turn off one bit.
CxxUtils::ConcurrentBitset::reference::flip
reference & flip() noexcept
Invert the referenced bit.
value_type
Definition: EDM_MasterSearch.h:11
xAOD::bool
setBGCode setTAP setLVL2ErrorBits bool
Definition: TrigDecision_v1.cxx:60
CxxUtils::ConcurrentBitset::nBlocks
static bit_t nBlocks(bit_t nbits)
Find number of blocks needed to hold a given number of bits.
bitscan.h
Bit scanning functions.
CxxUtils::ConcurrentBitset::const_iterator::operator*
bit_t operator*() const
Return the bit number which the iterator is currently referencing.
CxxUtils::ConcurrentBitset::const_iterator::ConcurrentBitset
friend ConcurrentBitset
Definition: ConcurrentBitset.h:704
CxxUtils::ConcurrentBitset::Impl::Impl
Impl(bit_t nbits)
Constructor.
CxxUtils::ConcurrentBitset::test
bool test(bit_t bit) const
Test to see if a bit is set.