| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright (C) 2010 Apple Inc. All rights reserved. | |
| 3 * | |
| 4 * This library is free software; you can redistribute it and/or | |
| 5 * modify it under the terms of the GNU Lesser General Public | |
| 6 * License as published by the Free Software Foundation; either | |
| 7 * version 2 of the License, or (at your option) any later version. | |
| 8 * | |
| 9 * This library is distributed in the hope that it will be useful, | |
| 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| 12 * Lesser General Public License for more details. | |
| 13 * | |
| 14 * You should have received a copy of the GNU Lesser General Public | |
| 15 * License along with this library; if not, write to the Free Software | |
| 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 U
SA | |
| 17 * | |
| 18 */ | |
| 19 #ifndef Bitmap_h | |
| 20 #define Bitmap_h | |
| 21 | |
| 22 #include <wtf/Atomics.h> | |
| 23 #include <wtf/FixedArray.h> | |
| 24 #include <wtf/StdLibExtras.h> | |
| 25 #include <stdint.h> | |
| 26 #include <string.h> | |
| 27 | |
| 28 namespace WTF { | |
| 29 | |
| 30 enum BitmapAtomicMode { | |
| 31 // This makes concurrentTestAndSet behave just like testAndSet. | |
| 32 BitmapNotAtomic, | |
| 33 | |
| 34 // This makes concurrentTestAndSet use compareAndSwap, so that it's | |
| 35 // atomic even when used concurrently. | |
| 36 BitmapAtomic | |
| 37 }; | |
| 38 | |
| 39 template<size_t size, BitmapAtomicMode atomicMode = BitmapNotAtomic> | |
| 40 class Bitmap { | |
| 41 private: | |
| 42 typedef uint32_t WordType; | |
| 43 | |
| 44 public: | |
| 45 Bitmap(); | |
| 46 | |
| 47 bool get(size_t) const; | |
| 48 void set(size_t); | |
| 49 bool testAndSet(size_t); | |
| 50 bool testAndClear(size_t); | |
| 51 bool concurrentTestAndSet(size_t); | |
| 52 bool concurrentTestAndClear(size_t); | |
| 53 size_t nextPossiblyUnset(size_t) const; | |
| 54 void clear(size_t); | |
| 55 void clearAll(); | |
| 56 int64_t findRunOfZeros(size_t) const; | |
| 57 size_t count(size_t = 0) const; | |
| 58 size_t isEmpty() const; | |
| 59 size_t isFull() const; | |
| 60 | |
| 61 private: | |
| 62 static const WordType wordSize = sizeof(WordType) * 8; | |
| 63 static const WordType words = (size + wordSize - 1) / wordSize; | |
| 64 | |
| 65 // the literal '1' is of type signed int. We want to use an unsigned | |
| 66 // version of the correct size when doing the calculations because if | |
| 67 // WordType is larger than int, '1 << 31' will first be sign extended | |
| 68 // and then casted to unsigned, meaning that set(31) when WordType is | |
| 69 // a 64 bit unsigned int would give 0xffff8000 | |
| 70 static const WordType one = 1; | |
| 71 | |
| 72 FixedArray<WordType, words> bits; | |
| 73 }; | |
| 74 | |
| 75 template<size_t size, BitmapAtomicMode atomicMode> | |
| 76 inline Bitmap<size, atomicMode>::Bitmap() | |
| 77 { | |
| 78 clearAll(); | |
| 79 } | |
| 80 | |
| 81 template<size_t size, BitmapAtomicMode atomicMode> | |
| 82 inline bool Bitmap<size, atomicMode>::get(size_t n) const | |
| 83 { | |
| 84 return !!(bits[n / wordSize] & (one << (n % wordSize))); | |
| 85 } | |
| 86 | |
| 87 template<size_t size, BitmapAtomicMode atomicMode> | |
| 88 inline void Bitmap<size, atomicMode>::set(size_t n) | |
| 89 { | |
| 90 bits[n / wordSize] |= (one << (n % wordSize)); | |
| 91 } | |
| 92 | |
| 93 template<size_t size, BitmapAtomicMode atomicMode> | |
| 94 inline bool Bitmap<size, atomicMode>::testAndSet(size_t n) | |
| 95 { | |
| 96 WordType mask = one << (n % wordSize); | |
| 97 size_t index = n / wordSize; | |
| 98 bool result = bits[index] & mask; | |
| 99 bits[index] |= mask; | |
| 100 return result; | |
| 101 } | |
| 102 | |
| 103 template<size_t size, BitmapAtomicMode atomicMode> | |
| 104 inline bool Bitmap<size, atomicMode>::testAndClear(size_t n) | |
| 105 { | |
| 106 WordType mask = one << (n % wordSize); | |
| 107 size_t index = n / wordSize; | |
| 108 bool result = bits[index] & mask; | |
| 109 bits[index] &= ~mask; | |
| 110 return result; | |
| 111 } | |
| 112 | |
| 113 template<size_t size, BitmapAtomicMode atomicMode> | |
| 114 inline bool Bitmap<size, atomicMode>::concurrentTestAndSet(size_t n) | |
| 115 { | |
| 116 if (atomicMode == BitmapNotAtomic) | |
| 117 return testAndSet(n); | |
| 118 | |
| 119 ASSERT(atomicMode == BitmapAtomic); | |
| 120 | |
| 121 WordType mask = one << (n % wordSize); | |
| 122 size_t index = n / wordSize; | |
| 123 WordType* wordPtr = bits.data() + index; | |
| 124 WordType oldValue; | |
| 125 do { | |
| 126 oldValue = *wordPtr; | |
| 127 if (oldValue & mask) | |
| 128 return true; | |
| 129 } while (!weakCompareAndSwap(wordPtr, oldValue, oldValue | mask)); | |
| 130 return false; | |
| 131 } | |
| 132 | |
| 133 template<size_t size, BitmapAtomicMode atomicMode> | |
| 134 inline bool Bitmap<size, atomicMode>::concurrentTestAndClear(size_t n) | |
| 135 { | |
| 136 if (atomicMode == BitmapNotAtomic) | |
| 137 return testAndClear(n); | |
| 138 | |
| 139 ASSERT(atomicMode == BitmapAtomic); | |
| 140 | |
| 141 WordType mask = one << (n % wordSize); | |
| 142 size_t index = n / wordSize; | |
| 143 WordType* wordPtr = bits.data() + index; | |
| 144 WordType oldValue; | |
| 145 do { | |
| 146 oldValue = *wordPtr; | |
| 147 if (!(oldValue & mask)) | |
| 148 return false; | |
| 149 } while (!weakCompareAndSwap(wordPtr, oldValue, oldValue & ~mask)); | |
| 150 return true; | |
| 151 } | |
| 152 | |
| 153 template<size_t size, BitmapAtomicMode atomicMode> | |
| 154 inline void Bitmap<size, atomicMode>::clear(size_t n) | |
| 155 { | |
| 156 bits[n / wordSize] &= ~(one << (n % wordSize)); | |
| 157 } | |
| 158 | |
| 159 template<size_t size, BitmapAtomicMode atomicMode> | |
| 160 inline void Bitmap<size, atomicMode>::clearAll() | |
| 161 { | |
| 162 memset(bits.data(), 0, sizeof(bits)); | |
| 163 } | |
| 164 | |
| 165 template<size_t size, BitmapAtomicMode atomicMode> | |
| 166 inline size_t Bitmap<size, atomicMode>::nextPossiblyUnset(size_t start) const | |
| 167 { | |
| 168 if (!~bits[start / wordSize]) | |
| 169 return ((start / wordSize) + 1) * wordSize; | |
| 170 return start + 1; | |
| 171 } | |
| 172 | |
| 173 template<size_t size, BitmapAtomicMode atomicMode> | |
| 174 inline int64_t Bitmap<size, atomicMode>::findRunOfZeros(size_t runLength) const | |
| 175 { | |
| 176 if (!runLength) | |
| 177 runLength = 1; | |
| 178 | |
| 179 for (size_t i = 0; i <= (size - runLength) ; i++) { | |
| 180 bool found = true; | |
| 181 for (size_t j = i; j <= (i + runLength - 1) ; j++) { | |
| 182 if (get(j)) { | |
| 183 found = false; | |
| 184 break; | |
| 185 } | |
| 186 } | |
| 187 if (found) | |
| 188 return i; | |
| 189 } | |
| 190 return -1; | |
| 191 } | |
| 192 | |
| 193 template<size_t size, BitmapAtomicMode atomicMode> | |
| 194 inline size_t Bitmap<size, atomicMode>::count(size_t start) const | |
| 195 { | |
| 196 size_t result = 0; | |
| 197 for ( ; (start % wordSize); ++start) { | |
| 198 if (get(start)) | |
| 199 ++result; | |
| 200 } | |
| 201 for (size_t i = start / wordSize; i < words; ++i) | |
| 202 result += WTF::bitCount(bits[i]); | |
| 203 return result; | |
| 204 } | |
| 205 | |
| 206 template<size_t size, BitmapAtomicMode atomicMode> | |
| 207 inline size_t Bitmap<size, atomicMode>::isEmpty() const | |
| 208 { | |
| 209 for (size_t i = 0; i < words; ++i) | |
| 210 if (bits[i]) | |
| 211 return false; | |
| 212 return true; | |
| 213 } | |
| 214 | |
| 215 template<size_t size, BitmapAtomicMode atomicMode> | |
| 216 inline size_t Bitmap<size, atomicMode>::isFull() const | |
| 217 { | |
| 218 for (size_t i = 0; i < words; ++i) | |
| 219 if (~bits[i]) | |
| 220 return false; | |
| 221 return true; | |
| 222 } | |
| 223 | |
| 224 } | |
| 225 #endif | |
| OLD | NEW |