9
9
#include < cassert>
10
10
11
11
12
- // ---------------------------------------------------------
13
- // BitField<>: Used internally by BEGIN_BITFIELD_TYPE macro.
14
- // T is expected to be an unsigned integral type.
15
- // ---------------------------------------------------------
16
- template <class T >
17
- struct BitField
18
- {
19
- typedef T IntType;
20
- T value;
21
-
22
- BitField (T v = 0 ) : value(v) {}
23
- BitField& baseCast () { return *this ; }
24
- const BitField& baseCast () const { return *this ; }
25
- };
26
-
27
-
28
12
// ---------------------------------------------------------
29
13
// BitFieldMember<>: Used internally by ADD_BITFIELD_MEMBER macro.
30
14
// ---------------------------------------------------------
31
15
template <class T , int Offset, int Bits>
32
- struct BitFieldMember : BitField<T>
16
+ class BitFieldMember
33
17
{
18
+ private:
34
19
static_assert (Offset + Bits <= (int ) sizeof (T) * 8 , " Member exceeds bitfield boundaries" );
35
20
static_assert (Bits < (int ) sizeof (T) * 8 , " Can't fill entire bitfield with one member" );
36
21
37
- // Compile-time constants.
38
- // Not easy to access since the template instance is wrapped in a macro.
39
- // You can get at them using eg. BitFieldType().member().maximum() instead.
40
22
static const T Maximum = (T(1 ) << Bits) - 1 ;
41
23
static const T Mask = Maximum << Offset;
42
24
43
- // Can't instantiate this class directly.
44
- // Must instead cast from BitField<T>.
45
- // That's what ADD_BITFIELD_MEMBER does.
46
- BitFieldMember () = delete ;
25
+ T value;
47
26
27
+ public:
48
28
T maximum () const { return Maximum; }
49
29
T one () const { return T (1 ) << Offset; }
50
30
51
- T get () const
31
+ operator T () const
52
32
{
53
- return (this -> value >> Offset) & Maximum;
33
+ return (value >> Offset) & Maximum;
54
34
}
55
35
56
- void set (T v)
36
+ BitFieldMember& operator = (T v)
57
37
{
58
- assert (v <= Maximum); // v must fit inside the bitfield member
59
- this ->value = (this ->value & ~Mask) | (v << Offset);
38
+ assert (v <= Maximum); // v must fit inside the bitfield member
39
+ value = (value & ~Mask) | (v << Offset);
40
+ return *this ;
60
41
}
61
42
62
- void setWrapped (T v)
43
+ BitFieldMember& operator += (T v)
63
44
{
64
- this ->value = (this ->value & ~Mask) | ((v & Maximum) << Offset);
45
+ assert (T (*this ) + v <= Maximum); // result must fit inside the bitfield member
46
+ value += v << Offset;
47
+ return *this ;
65
48
}
66
49
67
- void add (T v)
50
+ BitFieldMember& operator -= (T v)
68
51
{
69
- assert (get () + v <= Maximum); // result must fit inside the bitfield member
70
- this ->value += v << Offset;
52
+ assert (T (*this ) >= v); // result must not underflow
53
+ value -= v << Offset;
54
+ return *this ;
71
55
}
72
56
73
- void addWrapped (T v)
74
- {
75
- this ->value = (this ->value & ~Mask) | ((this ->value + (v << Offset)) & Mask);
76
- }
77
-
78
- void sub (T v)
79
- {
80
- assert (get () >= v); // result must not underflow
81
- this ->value -= v << Offset;
82
- }
83
-
84
- void subWrapped (T v)
85
- {
86
- this ->value = (this ->value & ~Mask) | ((this ->value - (v << Offset)) & Mask);
87
- }
57
+ BitFieldMember& operator ++() { return *this += 1 ; }
58
+ BitFieldMember& operator ++(int ) { return *this += 1 ; } // postfix form
59
+ BitFieldMember& operator --() { return *this -= 1 ; }
60
+ BitFieldMember& operator --(int ) { return *this -= 1 ; } // postfix form
88
61
};
89
62
90
63
91
64
// ---------------------------------------------------------
92
65
// BitFieldArray<>: Used internally by ADD_BITFIELD_ARRAY macro.
93
66
// ---------------------------------------------------------
94
67
template <class T , int BaseOffset, int BitsPerItem, int NumItems>
95
- struct BitFieldArray : BitField<T>
68
+ class BitFieldArray
96
69
{
70
+ private:
97
71
static_assert (BaseOffset + BitsPerItem * NumItems <= (int ) sizeof (T) * 8 , " Array exceeds bitfield boundaries" );
98
72
static_assert (BitsPerItem < (int ) sizeof (T) * 8 , " Can't fill entire bitfield with one array element" );
99
73
100
- // Compile-time constants.
101
- // Not easy to access since the template instance is wrapped in a macro.
102
- // You can get at them using eg. BitFieldType().member().maximum() instead.
103
74
static const T Maximum = (T(1 ) << BitsPerItem) - 1 ;
104
75
105
- // Can't instantiate this class directly.
106
- // Must instead cast from BitField<T>.
107
- // That's what ADD_BITFIELD_ARRAY does.
108
- BitFieldArray () = delete ;
109
-
110
- T maximum () const { return Maximum; }
111
- int offset (int i) const
112
- {
113
- assert (i >= 0 && i < NumItems); // array index must be in range
114
- return BaseOffset + BitsPerItem * i;
115
- }
116
- T one (int i) const { return T (1 ) << offset (i); }
117
- T mask (int i) const { return Maximum << offset (i); }
118
- int numItems () const { return NumItems; }
119
-
120
- T get (int i) const
121
- {
122
- return (this ->value >> offset (i)) & Maximum;
123
- }
124
-
125
- void set (int i, T v)
126
- {
127
- assert (v <= Maximum); // v must fit inside the bitfield member
128
- this ->value = (this ->value & ~mask (i)) | (v << offset (i));
129
- }
130
-
131
- void setWrapped (int i, T v)
132
- {
133
- this ->value = (this ->value & ~mask (i)) | ((v & Maximum) << offset (i));
134
- }
76
+ T value;
135
77
136
- void add ( int i, T v)
78
+ class Element
137
79
{
138
- assert (get (i) + v <= Maximum); // result must fit inside the bitfield member
139
- this ->value += v << offset (i);
140
- }
80
+ private:
81
+ T& value;
82
+ int offset;
83
+
84
+ public:
85
+ Element (T& value, int offset) : value(value), offset(offset) {}
86
+ T mask () const { return Maximum << offset; }
87
+
88
+ operator T () const
89
+ {
90
+ return (value >> offset) & Maximum;
91
+ }
92
+
93
+ Element& operator =(T v)
94
+ {
95
+ assert (v <= Maximum); // v must fit inside the bitfield member
96
+ value = (value & ~mask ()) | (v << offset);
97
+ return *this ;
98
+ }
99
+
100
+ Element& operator +=(T v)
101
+ {
102
+ assert (T (*this ) + v <= Maximum); // result must fit inside the bitfield member
103
+ value += v << offset;
104
+ return *this ;
105
+ }
106
+
107
+ Element& operator -=(T v)
108
+ {
109
+ assert (T (*this ) >= v); // result must not underflow
110
+ value -= v << offset;
111
+ return *this ;
112
+ }
113
+
114
+ Element& operator ++() { return *this += 1 ; }
115
+ Element& operator ++(int ) { return *this += 1 ; } // postfix form
116
+ Element& operator --() { return *this -= 1 ; }
117
+ Element& operator --(int ) { return *this -= 1 ; } // postfix form
118
+ };
141
119
142
- void addWrapped (int i, T v)
143
- {
144
- T m = mask (i);
145
- this ->value = (this ->value & ~m) | ((this ->value + (v << offset (i))) & m);
146
- }
120
+ public:
121
+ T maximum () const { return Maximum; }
122
+ int numItems () const { return NumItems; }
147
123
148
- void sub (int i, T v )
124
+ Element operator [] (int i)
149
125
{
150
- assert (get (i) >= v ); // result must not underflow
151
- this -> value -= v << offset ( i);
126
+ assert (i >= 0 && i < NumItems ); // array index must be in range
127
+ return Element ( value, BaseOffset + BitsPerItem * i);
152
128
}
153
129
154
- void subWrapped (int i, T v)
130
+ const Element operator [] (int i) const
155
131
{
156
- T m = mask (i);
157
- this -> value = ( this -> value & ~m) | (( this -> value - (v << offset (i))) & m );
132
+ assert (i >= 0 && i < NumItems); // array index must be in range
133
+ return Element ( value, BaseOffset + BitsPerItem * i );
158
134
}
159
135
};
160
136
@@ -164,17 +140,22 @@ struct BitFieldArray : BitField<T>
164
140
// For usage examples, see RWLock and LockReducedDiningPhilosophers.
165
141
// ---------------------------------------------------------
166
142
#define BEGIN_BITFIELD_TYPE (typeName, T ) \
167
- struct typeName : BitField<T> \
143
+ union typeName \
168
144
{ \
169
- typeName (T v = 0 ) : BitField(v) {}
145
+ private: \
146
+ typedef T _IntType; \
147
+ T value; \
148
+ public: \
149
+ typeName (T v = 0 ) : value (v) {} \
150
+ typeName& operator =(T v) { value = v; return *this ; } \
151
+ operator T&() { return value; } \
152
+ operator T () const { return value; }
170
153
171
154
#define ADD_BITFIELD_MEMBER (memberName, offset, bits ) \
172
- BitFieldMember<IntType, offset, bits>& memberName () { return static_cast <BitFieldMember<IntType, offset, bits>&>(baseCast ()); } \
173
- const BitFieldMember<IntType, offset, bits>& memberName () const { return static_cast <const BitFieldMember<IntType, offset, bits>&>(baseCast ()); }
155
+ BitFieldMember<_IntType, offset, bits> memberName;
174
156
175
- #define ADD_BITFIELD_ARRAY (memberName, offset, bitsPerItem, numItems ) \
176
- BitFieldArray<IntType, offset, bitsPerItem, numItems>& memberName () { return static_cast <BitFieldArray<IntType, offset, bitsPerItem, numItems>&>(baseCast ()); } \
177
- const BitFieldArray<IntType, offset, bitsPerItem, numItems>& memberName () const { return static_cast <const BitFieldArray<IntType, offset, bitsPerItem, numItems>&>(baseCast ()); }
157
+ #define ADD_BITFIELD_ARRAY (memberName, offset, bits, numItems ) \
158
+ BitFieldArray<_IntType, offset, bits, numItems> memberName;
178
159
179
160
#define END_BITFIELD_TYPE () \
180
161
};
0 commit comments