ATLAS Offline Software
Loading...
Searching...
No Matches
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 */
13
14
15#ifndef CXXUTILS_CONCURRENTBITSET_H
16#define CXXUTILS_CONCURRENTBITSET_H
17
18
20#include "CxxUtils/features.h"
21#include "CxxUtils/ones.h"
22#include <climits>
23#include <vector>
24#include <algorithm>
25#include <iterator>
26#include <atomic>
27#include <mutex>
28#include <memory>
29#include <type_traits>
30#include <cstddef>
31#include <bit>
32
33
34namespace CxxUtils {
35
36
145{
146private:
147 // Forward declaration of implementation class.
148 class Impl;
149
154 typedef unsigned long Block_t;
155
157 static const size_t BLOCKSIZE = sizeof(Block_t) * CHAR_BIT;
158
160 static const size_t MASK = BLOCKSIZE-1;
161
162
163 static_assert (std::atomic<Block_t>::is_always_lock_free);
164
165public:
167 typedef size_t bit_t;
168
169
170 //========================================================================
173
174
179 ConcurrentBitset (bit_t nbits = 0);
180
181
189 ConcurrentBitset (const ConcurrentBitset& other);
190
191
203 ConcurrentBitset (std::initializer_list<bit_t> l, bit_t nbits = 0);
204
205
214
215
220
221
230
231
240
241
250 void emptyGarbage();
251
252
254 //========================================================================
257
258
263
264
268 bit_t count() const;
269
270
279 bit_t size() const;
280
281
289 bool test (bit_t bit) const;
290
291
299 size_t count (bit_t bit) const;
300
301
305 bool empty() const;
306
307
311 bool none() const;
312
313
317 bool all() const;
318
319
323 bool any() const;
324
325
327 //========================================================================
330
331
339
340
348
349
357
358
366
367
375 ConcurrentBitset& set (bit_t bit, bool val);
376
377
379 //========================================================================
382
383
391
392
400
401
409
410
418
419
428
429
438
439
448
449
460
461
466
467
469 //========================================================================
472
473
478 bool operator== (const ConcurrentBitset& other) const;
479
480
485 bool operator!= (const ConcurrentBitset& other) const;
486
487
489 //========================================================================
492
493
505 ConcurrentBitset& insert (bit_t bit, bit_t new_nbits = 0);
506
507
528 // The enable_if is needed to keep this something like
529 // bs.insert (1, 2)
530 // from matching this overload.
531 template <class ITERATOR,
532 typename = typename std::enable_if<
533 std::is_base_of<
534 typename std::forward_iterator_tag,
535 typename std::iterator_traits<ITERATOR>::iterator_category
536 >::value> >
537 ConcurrentBitset& insert (ITERATOR beg, ITERATOR end, bit_t new_nbits = 0);
538
539
557 ConcurrentBitset& insert (std::initializer_list<bit_t> l, bit_t new_nbits = 0);
558
559
571
572
574 //========================================================================
577
578
585 {
586 private:
587 friend class ConcurrentBitset;
588
589
596
597
598 public:
603 reference& operator= (bool val) noexcept;
604
605
617 reference& operator= (const reference& r) noexcept;
618
619
623 operator bool() const noexcept;
624
625
629 bool operator~() const noexcept;
630
631
635 reference& flip() noexcept;
636
637
638 private:
640 std::atomic<Block_t>* m_block;
641
644 };
645
646
651 bool operator[] (bit_t bit) const;
652
653
661 reference operator[] (bit_t bit);
662
663
665 //========================================================================
668
669
694 {
695 typedef std::forward_iterator_tag iterator_category;
696 typedef size_t value_type;
697 typedef ptrdiff_t difference_type;
698 typedef const value_type* pointer;
699 typedef const value_type& reference;
700
701
702 private:
704
705
715 bit_t bit,
716 const std::atomic<Block_t>* data,
717 const std::atomic<Block_t>* end);
718
719
720 public:
725
726
731
732
737
738
743 bool operator== (const const_iterator& other) const;
744
745
750 bool operator!= (const const_iterator& other) const;
751
752
753 private:
758
761
763 const std::atomic<Block_t>* m_data;
764
765
767 const std::atomic<Block_t>* m_end;
768 };
769
770
775
776
781
782
789
790
791
793private:
794 //========================================================================
797
798
803 static bit_t nBlocks (bit_t nbits);
804
805
814
815
820 void expand (bit_t new_nbits);
821
822
827 void expandOol (bit_t new_nbits);
828
829
844 class Impl
845 {
846 public:
852 void* operator new (size_t /*sz*/, bit_t nbits);
853
854
855 /*
856 * @brief Free an Impl structure.
857 * @param p Pointer to the object to free.
858 */
859 void operator delete (void* p);
860
861
867
868
877 Impl (const Impl& other, bit_t nbits = 0);
878
879
880 // Assignment is unimplemented.
881 Impl& operator= (const Impl&) = delete;
882
883
893 void assign (const Impl& other);
894
895
899 bit_t nbits() const;
900
901
909 bool test (bit_t bit) const;
910
911
915 bit_t count() const;
916
917
921 bool none() const;
922
923
927 bool all() const;
928
929
936 std::atomic<Block_t>* block (bit_t bit);
937
938
945 void set (bit_t bit);
946
947
954 void reset (bit_t bit);
955
956
963 void flip (bit_t bit);
964
965
972 void clear();
973
974
981 void set();
982
983
990 void flip();
991
992
993 typedef void operator_t (std::atomic<Block_t>& a, Block_t v);
1003 void operate (operator_t op, const Impl& other);
1004
1005
1010 bool operator== (const Impl& other) const;
1011
1012
1013
1018
1019
1024
1025
1032
1033
1034 private:
1036 size_t m_nbits;
1037
1040
1042 std::atomic<size_t> m_hwm;
1043
1047 std::atomic<Block_t> m_data[1];
1048 };
1049
1050
1052
1053
1054private:
1056 std::atomic<Impl*> m_impl;
1057
1059 std::vector<Impl*> m_garbage;
1060
1062 typedef std::mutex mutex_t;
1063 typedef std::lock_guard<mutex_t> lock_t;
1065};
1066
1067
1068} // namespace CxxUtils
1069
1070
1072
1073
1074#endif // not CXXUTILS_CONCURRENTBITSET_H
bool operator==(const DataVector< T > &a, const DataVector< T > &b)
Vector equality comparison.
char data[hepevt_bytes_allocation_ATLAS]
Definition HepEvt.cxx:11
static Double_t a
Atomic min/max functions.
const_iterator find(bit_t bit) const
If bit bit is set, return an iterator pointing to it.
bit_t nbits() const
Return the number of bits in the set.
bool test(bit_t bit) const
Test to see if a bit is set.
Impl(const Impl &other, bit_t nbits=0)
Copy constructor.
const_iterator begin() const
Return an iterator referencing the first 1 bit.
std::atomic< size_t > m_hwm
High-water mark: index of last block with a 1 bit.
void flip(bit_t bit)
Flip the value of one bit.
bool all() const
Return true if all bits in the set are 1.
void operator_t(std::atomic< Block_t > &a, Block_t v)
void set(bit_t bit)
Turn on one bit.
void assign(const Impl &other)
Copy from another instance.
const_iterator end() const
Return the end iterator.
void clear()
Clear all bits in the set.
std::atomic< Block_t > * block(bit_t bit)
Return a pointer to the block containing bit.
Impl(bit_t nbits)
Constructor.
void reset(bit_t bit)
Turn off one bit.
void operate(operator_t op, const Impl &other)
Apply a binary operation.
size_t m_nbits
Number of bits in the container.
bool none() const
Return true if there are no 1 bits in the set.
size_t m_nblocks
Number of blocks in the container.
std::atomic< Block_t > m_data[1]
The set data.
A reference to one bit in a set.
reference & flip() noexcept
Invert the referenced bit.
std::atomic< Block_t > * m_block
Pointer to the block containing the referenced bit.
reference(Impl &impl, bit_t bit)
Constructor.
reference & operator=(bool val) noexcept
Set the referenced bit to a given value.
Block_t m_mask
Mask of the referenced bit within the block.
const_iterator end() const
Return an end iterator.
bool operator==(const ConcurrentBitset &other) const
Test two sets for equality.
void emptyGarbage()
Clean up old versions of the set.
ConcurrentBitset & flip(bit_t bit)
Flip the value of one bit.
void expandOol(bit_t new_nbits)
Expand the container: out-of-line portion.
std::lock_guard< mutex_t > lock_t
ConcurrentBitset & insert(ITERATOR beg, ITERATOR end, bit_t new_nbits=0)
Set several bits to 1.
bool test(bit_t bit) const
Test to see if a bit is set.
unsigned long Block_t
Internal type used to hold the bitset data.
ConcurrentBitset & erase(bit_t bit)
Turn off one bit.
bool any() const
Return true if there are any 1 bits in the set.
ConcurrentBitset & set(bit_t bit, bool val)
Set the value of one bit.
ConcurrentBitset(bit_t nbits=0)
Constructor.
ConcurrentBitset & set(bit_t bit)
Turn on one bit.
ConcurrentBitset & operator-=(const ConcurrentBitset &other)
Subtract another set from this set.
bit_t size() const
Count the number of 1 bits in the set.
ConcurrentBitset & reset()
Clear all bits in the set.
ConcurrentBitset & insert(std::initializer_list< bit_t > l, bit_t new_nbits=0)
Set several bits to 1.
bool none() const
Return true if there are no 1 bits in the set.
ConcurrentBitset & operator|=(const ConcurrentBitset &other)
OR this set with another set.
void expand(bit_t new_nbits)
Expand the container.
ConcurrentBitset & insert(bit_t bit, bit_t new_nbits=0)
Set a bit to 1.
static const size_t BLOCKSIZE
Size, in bits, of Block_t.
bit_t capacity() const
The number of bits that this container can hold.
const_iterator begin() const
Return a begin iterator.
bool empty() const
Return true if there are no 1 bits in the set.
bool all() const
Return true if all bits in the set are 1.
std::atomic< Impl * > m_impl
The current implementation object.
bit_t count() const
Count the number of 1 bits in the set.
ConcurrentBitset & insert(const ConcurrentBitset &other)
Turn on bits listed in another set.
ConcurrentBitset & operator&=(const ConcurrentBitset &other)
AND this set with another set.
std::mutex mutex_t
Mutex used for synchronization when switching to a new implementation object.
ConcurrentBitset & reset(bit_t bit)
Turn off one bit.
ConcurrentBitset & flip()
Flip the state of all bits in the set.
const_iterator find(bit_t bit) const
If bit bit is set, return an iterator pointing to it.
static bit_t nBlocks(bit_t nbits)
Find number of blocks needed to hold a given number of bits.
size_t count(bit_t bit) const
Test to see if a bit is set.
ConcurrentBitset & set()
Turn on all bits in the set.
std::vector< Impl * > m_garbage
Old implementation objects, pending deletion.
Impl * newImpl(bit_t nbits)
Create a new, uninitialized implementation object.
ConcurrentBitset & operator=(const ConcurrentBitset &other)
Assignment.
ConcurrentBitset operator~() const
Return a new set that is the complement of this set.
ConcurrentBitset & clear()
Clear all bits in the set.
ConcurrentBitset & operator^=(const ConcurrentBitset &other)
XOR this set with another set.
static const size_t MASK
Mask to select out the bit offset within one Block_t.
bool operator!=(const ConcurrentBitset &other) const
Test two sets for inequality.
Some additional feature test macros.
int r
Definition globals.cxx:22
int count(std::string s, const std::string &regx)
count how many occurances of a regx are in a string
Definition hcg.cxx:146
STL namespace.
Construct a bit mask.
Iterator over all 1 bits in the set.
Block_t m_cache
Cache of the block to which we're currently pointing.
const_iterator(Block_t cache, bit_t bit, const std::atomic< Block_t > *data, const std::atomic< Block_t > *end)
Constructor.
const std::atomic< Block_t > * m_end
Pointer to one past the last block in the set.
const std::atomic< Block_t > * m_data
Pointer to the block containing the bit which we're currently referencing.
bit_t m_bit
Bit number which we're currently referencing.
bit_t operator*() const
Return the bit number which the iterator is currently referencing.
const_iterator & operator++()
Advance the iterator to the next set bit (preincrement).
const_iterator operator++(int)
Advance the iterator to the next set bit (postincrement).
#define private