1// Licensed to the .NET Foundation under one or more agreements.
2// The .NET Foundation licenses this file to you under the MIT license.
3// See the LICENSE file in the project root for more information.
4
5//
6
7// --------------------------------------------------------------------------------
8// BitMask.inl
9// --------------------------------------------------------------------------------
10
11#include <bitmask.h>
12
13#ifndef _BITMASK_INL_
14#define _BITMASK_INL_
15
16inline BOOL BitMask::IsArray()
17{
18 LIMITED_METHOD_CONTRACT;
19 return (m_mask&1) == 0;
20}
21
22// Indexing computations
23inline COUNT_T BitMask::BitToIndex(int bit)
24{
25 LIMITED_METHOD_CONTRACT;
26 // First word has one less bit due to tag
27 return (bit+1) >> BIT_SIZE_SHIFT;
28}
29
30inline COUNT_T BitMask::BitToShift(int bit)
31{
32 LIMITED_METHOD_CONTRACT;
33 // First word has one less bit due to tag
34 return (bit+1) & BIT_SIZE_MASK;
35}
36
37// Array access. Note the first array element is the count of the
38// rest of the elements
39
40inline COUNT_T *BitMask::GetMaskArray()
41{
42 LIMITED_METHOD_CONTRACT;
43 if (IsArray())
44 {
45 CONSISTENCY_CHECK(CheckPointer(m_maskArray));
46 return m_maskArray+1;
47 }
48 else
49 return &m_mask;
50}
51
52inline COUNT_T BitMask::GetMaskArraySize()
53{
54 LIMITED_METHOD_CONTRACT;
55 if (IsArray())
56 return *m_maskArray;
57 else
58 return 1;
59}
60
61inline void BitMask::GrowArray(COUNT_T newSize)
62{
63 CONTRACTL
64 {
65 THROWS;
66 }
67 CONTRACTL_END;
68
69 // Ensure we don't grow too often
70
71 COUNT_T oldSize = GetMaskArraySize();
72 if (newSize <= oldSize)
73 return;
74
75 if (newSize < oldSize*2)
76 newSize = oldSize*2;
77 if (newSize < MIN_ARRAY_ALLOCATION)
78 newSize = MIN_ARRAY_ALLOCATION;
79
80 // Allocate new array
81
82 COUNT_T *newArray = new COUNT_T [newSize+1];
83 *newArray = newSize;
84
85 CopyMemory(newArray+1, GetMaskArray(), oldSize * sizeof(COUNT_T));
86 ZeroMemory(newArray+oldSize+1, (newSize - oldSize) * sizeof(COUNT_T));
87
88 if (IsArray())
89 delete [] m_maskArray;
90
91 m_maskArray = newArray;
92}
93
94inline BitMask::BitMask()
95 : m_mask(1)
96{
97 LIMITED_METHOD_CONTRACT;
98}
99
100inline BitMask::~BitMask()
101{
102 LIMITED_METHOD_CONTRACT;
103
104 if (IsArray())
105 delete [] m_maskArray;
106}
107
108inline BOOL BitMask::TestBit(int bit)
109{
110 LIMITED_METHOD_CONTRACT;
111
112 COUNT_T index = BitToIndex(bit);
113
114 if (index >= GetMaskArraySize())
115 return FALSE;
116
117 return ( GetMaskArray()[index] >> BitToShift(bit) ) & 1;
118}
119
120inline void BitMask::SetBit(int bit)
121{
122 CONTRACTL
123 {
124 THROWS;
125 }
126 CONTRACTL_END;
127
128 COUNT_T index = BitToIndex(bit);
129
130 if (index >= GetMaskArraySize())
131 GrowArray(index+1);
132
133 GetMaskArray()[index] |= (1 << BitToShift(bit));
134}
135
136inline void BitMask::ClearBit(int bit)
137{
138 LIMITED_METHOD_CONTRACT;
139
140 COUNT_T index = BitToIndex(bit);
141
142 if (index >= GetMaskArraySize())
143 return;
144
145 GetMaskArray()[index] &= ~(1 << BitToShift(bit));
146}
147
148inline BOOL BitMask::TestAnyBit()
149{
150 LIMITED_METHOD_CONTRACT;
151
152 if (IsArray())
153 {
154 COUNT_T *mask = m_maskArray+1;
155 COUNT_T *maskEnd = mask + m_maskArray[0];
156
157 while (mask < maskEnd)
158 {
159 if (*mask != 0)
160 return TRUE;
161 mask++;
162 }
163
164 return FALSE;
165 }
166 else
167 return m_mask != (COUNT_T) 1;
168}
169
170inline void BitMask::ClearAllBits()
171{
172 LIMITED_METHOD_CONTRACT;
173
174 if (IsArray())
175 delete [] m_maskArray;
176
177 m_mask = 1;
178}
179
180inline size_t BitMask::GetAllocatedBlockOffset()
181{
182 LIMITED_METHOD_CONTRACT;
183
184 return offsetof(BitMask, m_maskArray);
185}
186
187inline void *BitMask::GetAllocatedBlock()
188{
189 LIMITED_METHOD_CONTRACT;
190
191 if (IsArray())
192 return m_maskArray;
193 else
194 return NULL;
195}
196
197inline COUNT_T BitMask::GetAllocatedBlockSize()
198{
199 LIMITED_METHOD_CONTRACT;
200
201 if (IsArray())
202 return (GetMaskArraySize()+1) * sizeof(COUNT_T);
203 else
204 return 0;
205}
206
207/////////////////////////////////////////////////////////////////////////////////////////////
208/////////////////////////////////////////////////////////////////////////////////////////////
209
210inline SynchronizedBitMask::SynchronizedBitMask()
211 : m_bitMaskLock(PREEMPTIVE, LOCK_TYPE_DEFAULT)
212{
213 LIMITED_METHOD_CONTRACT;
214}
215
216inline BOOL SynchronizedBitMask::TestBit(int bit)
217{
218 CONTRACTL
219 {
220 NOTHROW;
221 MODE_ANY;
222 CAN_TAKE_LOCK;
223 }
224 CONTRACTL_END;
225
226 SimpleReadLockHolder holder(&m_bitMaskLock);
227
228 return m_bitMask.TestBit(bit);
229}
230
231inline void SynchronizedBitMask::SetBit(int bit)
232{
233 CONTRACTL
234 {
235 THROWS;
236 MODE_ANY;
237 CAN_TAKE_LOCK;
238 }
239 CONTRACTL_END;
240
241 SimpleWriteLockHolder holder(&m_bitMaskLock);
242
243 m_bitMask.SetBit(bit);
244}
245
246inline void SynchronizedBitMask::ClearBit(int bit)
247{
248 CONTRACTL
249 {
250 NOTHROW;
251 MODE_ANY;
252 CAN_TAKE_LOCK;
253 }
254 CONTRACTL_END;
255
256 SimpleWriteLockHolder holder(&m_bitMaskLock);
257
258 m_bitMask.ClearBit(bit);
259}
260
261inline BOOL SynchronizedBitMask::TestAnyBit()
262{
263 CONTRACTL
264 {
265 NOTHROW;
266 MODE_ANY;
267 CAN_TAKE_LOCK;
268 }
269 CONTRACTL_END;
270
271 SimpleReadLockHolder holder(&m_bitMaskLock);
272
273 return m_bitMask.TestAnyBit();
274}
275
276inline void SynchronizedBitMask::ClearAllBits()
277{
278 CONTRACTL
279 {
280 NOTHROW;
281 MODE_ANY;
282 CAN_TAKE_LOCK;
283 }
284 CONTRACTL_END;
285
286 SimpleWriteLockHolder holder(&m_bitMaskLock);
287
288 m_bitMask.ClearAllBits();
289}
290
291#endif // _BITMASK_INL_
292
293