| OLD | NEW |
| 1 | 1 |
| 2 /* | 2 /* |
| 3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
| 4 * | 4 * |
| 5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
| 6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
| 7 */ | 7 */ |
| 8 | 8 |
| 9 | 9 |
| 10 #include "SkDeque.h" | 10 #include "SkDeque.h" |
| 11 | 11 |
| 12 struct SkDeque::Block { | 12 struct SkDeque::Block { |
| 13 Block* fNext; | 13 Block* fNext; |
| 14 Block* fPrev; | 14 Block* fPrev; |
| 15 char* fBegin; // start of used section in this chunk | 15 char* fBegin; // start of used section in this chunk |
| 16 char* fEnd; // end of used section in this chunk | 16 char* fEnd; // end of used section in this chunk |
| 17 char* fStop; // end of the allocated chunk | 17 char* fStop; // end of the allocated chunk |
| 18 | 18 |
| 19 char* start() { return (char*)(this + 1); } | 19 char* start() { return (char*)(this + 1); } |
| 20 const char* start() const { return (const char*)(this + 1); } | 20 const char* start() const { return (const char*)(this + 1); } |
| 21 | 21 |
| 22 void init(size_t size) { | 22 void init(size_t size) { |
| 23 fNext = fPrev = NULL; | 23 fNext = fPrev = nullptr; |
| 24 fBegin = fEnd = NULL; | 24 fBegin = fEnd = nullptr; |
| 25 fStop = (char*)this + size; | 25 fStop = (char*)this + size; |
| 26 } | 26 } |
| 27 }; | 27 }; |
| 28 | 28 |
| 29 SkDeque::SkDeque(size_t elemSize, int allocCount) | 29 SkDeque::SkDeque(size_t elemSize, int allocCount) |
| 30 : fElemSize(elemSize) | 30 : fElemSize(elemSize) |
| 31 , fInitialStorage(NULL) | 31 , fInitialStorage(nullptr) |
| 32 , fCount(0) | 32 , fCount(0) |
| 33 , fAllocCount(allocCount) { | 33 , fAllocCount(allocCount) { |
| 34 SkASSERT(allocCount >= 1); | 34 SkASSERT(allocCount >= 1); |
| 35 fFrontBlock = fBackBlock = NULL; | 35 fFrontBlock = fBackBlock = nullptr; |
| 36 fFront = fBack = NULL; | 36 fFront = fBack = nullptr; |
| 37 } | 37 } |
| 38 | 38 |
| 39 SkDeque::SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCo
unt) | 39 SkDeque::SkDeque(size_t elemSize, void* storage, size_t storageSize, int allocCo
unt) |
| 40 : fElemSize(elemSize) | 40 : fElemSize(elemSize) |
| 41 , fInitialStorage(storage) | 41 , fInitialStorage(storage) |
| 42 , fCount(0) | 42 , fCount(0) |
| 43 , fAllocCount(allocCount) { | 43 , fAllocCount(allocCount) { |
| 44 SkASSERT(storageSize == 0 || storage != NULL); | 44 SkASSERT(storageSize == 0 || storage != nullptr); |
| 45 SkASSERT(allocCount >= 1); | 45 SkASSERT(allocCount >= 1); |
| 46 | 46 |
| 47 if (storageSize >= sizeof(Block) + elemSize) { | 47 if (storageSize >= sizeof(Block) + elemSize) { |
| 48 fFrontBlock = (Block*)storage; | 48 fFrontBlock = (Block*)storage; |
| 49 fFrontBlock->init(storageSize); | 49 fFrontBlock->init(storageSize); |
| 50 } else { | 50 } else { |
| 51 fFrontBlock = NULL; | 51 fFrontBlock = nullptr; |
| 52 } | 52 } |
| 53 fBackBlock = fFrontBlock; | 53 fBackBlock = fFrontBlock; |
| 54 fFront = fBack = NULL; | 54 fFront = fBack = nullptr; |
| 55 } | 55 } |
| 56 | 56 |
| 57 SkDeque::~SkDeque() { | 57 SkDeque::~SkDeque() { |
| 58 Block* head = fFrontBlock; | 58 Block* head = fFrontBlock; |
| 59 Block* initialHead = (Block*)fInitialStorage; | 59 Block* initialHead = (Block*)fInitialStorage; |
| 60 | 60 |
| 61 while (head) { | 61 while (head) { |
| 62 Block* next = head->fNext; | 62 Block* next = head->fNext; |
| 63 if (head != initialHead) { | 63 if (head != initialHead) { |
| 64 this->freeBlock(head); | 64 this->freeBlock(head); |
| 65 } | 65 } |
| 66 head = next; | 66 head = next; |
| 67 } | 67 } |
| 68 } | 68 } |
| 69 | 69 |
| 70 void* SkDeque::push_front() { | 70 void* SkDeque::push_front() { |
| 71 fCount += 1; | 71 fCount += 1; |
| 72 | 72 |
| 73 if (NULL == fFrontBlock) { | 73 if (nullptr == fFrontBlock) { |
| 74 fFrontBlock = this->allocateBlock(fAllocCount); | 74 fFrontBlock = this->allocateBlock(fAllocCount); |
| 75 fBackBlock = fFrontBlock; // update our linklist | 75 fBackBlock = fFrontBlock; // update our linklist |
| 76 } | 76 } |
| 77 | 77 |
| 78 Block* first = fFrontBlock; | 78 Block* first = fFrontBlock; |
| 79 char* begin; | 79 char* begin; |
| 80 | 80 |
| 81 if (NULL == first->fBegin) { | 81 if (nullptr == first->fBegin) { |
| 82 INIT_CHUNK: | 82 INIT_CHUNK: |
| 83 first->fEnd = first->fStop; | 83 first->fEnd = first->fStop; |
| 84 begin = first->fStop - fElemSize; | 84 begin = first->fStop - fElemSize; |
| 85 } else { | 85 } else { |
| 86 begin = first->fBegin - fElemSize; | 86 begin = first->fBegin - fElemSize; |
| 87 if (begin < first->start()) { // no more room in this chunk | 87 if (begin < first->start()) { // no more room in this chunk |
| 88 // should we alloc more as we accumulate more elements? | 88 // should we alloc more as we accumulate more elements? |
| 89 first = this->allocateBlock(fAllocCount); | 89 first = this->allocateBlock(fAllocCount); |
| 90 first->fNext = fFrontBlock; | 90 first->fNext = fFrontBlock; |
| 91 fFrontBlock->fPrev = first; | 91 fFrontBlock->fPrev = first; |
| 92 fFrontBlock = first; | 92 fFrontBlock = first; |
| 93 goto INIT_CHUNK; | 93 goto INIT_CHUNK; |
| 94 } | 94 } |
| 95 } | 95 } |
| 96 | 96 |
| 97 first->fBegin = begin; | 97 first->fBegin = begin; |
| 98 | 98 |
| 99 if (NULL == fFront) { | 99 if (nullptr == fFront) { |
| 100 SkASSERT(NULL == fBack); | 100 SkASSERT(nullptr == fBack); |
| 101 fFront = fBack = begin; | 101 fFront = fBack = begin; |
| 102 } else { | 102 } else { |
| 103 SkASSERT(fBack); | 103 SkASSERT(fBack); |
| 104 fFront = begin; | 104 fFront = begin; |
| 105 } | 105 } |
| 106 | 106 |
| 107 return begin; | 107 return begin; |
| 108 } | 108 } |
| 109 | 109 |
| 110 void* SkDeque::push_back() { | 110 void* SkDeque::push_back() { |
| 111 fCount += 1; | 111 fCount += 1; |
| 112 | 112 |
| 113 if (NULL == fBackBlock) { | 113 if (nullptr == fBackBlock) { |
| 114 fBackBlock = this->allocateBlock(fAllocCount); | 114 fBackBlock = this->allocateBlock(fAllocCount); |
| 115 fFrontBlock = fBackBlock; // update our linklist | 115 fFrontBlock = fBackBlock; // update our linklist |
| 116 } | 116 } |
| 117 | 117 |
| 118 Block* last = fBackBlock; | 118 Block* last = fBackBlock; |
| 119 char* end; | 119 char* end; |
| 120 | 120 |
| 121 if (NULL == last->fBegin) { | 121 if (nullptr == last->fBegin) { |
| 122 INIT_CHUNK: | 122 INIT_CHUNK: |
| 123 last->fBegin = last->start(); | 123 last->fBegin = last->start(); |
| 124 end = last->fBegin + fElemSize; | 124 end = last->fBegin + fElemSize; |
| 125 } else { | 125 } else { |
| 126 end = last->fEnd + fElemSize; | 126 end = last->fEnd + fElemSize; |
| 127 if (end > last->fStop) { // no more room in this chunk | 127 if (end > last->fStop) { // no more room in this chunk |
| 128 // should we alloc more as we accumulate more elements? | 128 // should we alloc more as we accumulate more elements? |
| 129 last = this->allocateBlock(fAllocCount); | 129 last = this->allocateBlock(fAllocCount); |
| 130 last->fPrev = fBackBlock; | 130 last->fPrev = fBackBlock; |
| 131 fBackBlock->fNext = last; | 131 fBackBlock->fNext = last; |
| 132 fBackBlock = last; | 132 fBackBlock = last; |
| 133 goto INIT_CHUNK; | 133 goto INIT_CHUNK; |
| 134 } | 134 } |
| 135 } | 135 } |
| 136 | 136 |
| 137 last->fEnd = end; | 137 last->fEnd = end; |
| 138 end -= fElemSize; | 138 end -= fElemSize; |
| 139 | 139 |
| 140 if (NULL == fBack) { | 140 if (nullptr == fBack) { |
| 141 SkASSERT(NULL == fFront); | 141 SkASSERT(nullptr == fFront); |
| 142 fFront = fBack = end; | 142 fFront = fBack = end; |
| 143 } else { | 143 } else { |
| 144 SkASSERT(fFront); | 144 SkASSERT(fFront); |
| 145 fBack = end; | 145 fBack = end; |
| 146 } | 146 } |
| 147 | 147 |
| 148 return end; | 148 return end; |
| 149 } | 149 } |
| 150 | 150 |
| 151 void SkDeque::pop_front() { | 151 void SkDeque::pop_front() { |
| 152 SkASSERT(fCount > 0); | 152 SkASSERT(fCount > 0); |
| 153 fCount -= 1; | 153 fCount -= 1; |
| 154 | 154 |
| 155 Block* first = fFrontBlock; | 155 Block* first = fFrontBlock; |
| 156 | 156 |
| 157 SkASSERT(first != NULL); | 157 SkASSERT(first != nullptr); |
| 158 | 158 |
| 159 if (first->fBegin == NULL) { // we were marked empty from before | 159 if (first->fBegin == nullptr) { // we were marked empty from before |
| 160 first = first->fNext; | 160 first = first->fNext; |
| 161 first->fPrev = NULL; | 161 first->fPrev = nullptr; |
| 162 this->freeBlock(fFrontBlock); | 162 this->freeBlock(fFrontBlock); |
| 163 fFrontBlock = first; | 163 fFrontBlock = first; |
| 164 SkASSERT(first != NULL); // else we popped too far | 164 SkASSERT(first != nullptr); // else we popped too far |
| 165 } | 165 } |
| 166 | 166 |
| 167 char* begin = first->fBegin + fElemSize; | 167 char* begin = first->fBegin + fElemSize; |
| 168 SkASSERT(begin <= first->fEnd); | 168 SkASSERT(begin <= first->fEnd); |
| 169 | 169 |
| 170 if (begin < fFrontBlock->fEnd) { | 170 if (begin < fFrontBlock->fEnd) { |
| 171 first->fBegin = begin; | 171 first->fBegin = begin; |
| 172 SkASSERT(first->fBegin); | 172 SkASSERT(first->fBegin); |
| 173 fFront = first->fBegin; | 173 fFront = first->fBegin; |
| 174 } else { | 174 } else { |
| 175 first->fBegin = first->fEnd = NULL; // mark as empty | 175 first->fBegin = first->fEnd = nullptr; // mark as empty |
| 176 if (NULL == first->fNext) { | 176 if (nullptr == first->fNext) { |
| 177 fFront = fBack = NULL; | 177 fFront = fBack = nullptr; |
| 178 } else { | 178 } else { |
| 179 SkASSERT(first->fNext->fBegin); | 179 SkASSERT(first->fNext->fBegin); |
| 180 fFront = first->fNext->fBegin; | 180 fFront = first->fNext->fBegin; |
| 181 } | 181 } |
| 182 } | 182 } |
| 183 } | 183 } |
| 184 | 184 |
| 185 void SkDeque::pop_back() { | 185 void SkDeque::pop_back() { |
| 186 SkASSERT(fCount > 0); | 186 SkASSERT(fCount > 0); |
| 187 fCount -= 1; | 187 fCount -= 1; |
| 188 | 188 |
| 189 Block* last = fBackBlock; | 189 Block* last = fBackBlock; |
| 190 | 190 |
| 191 SkASSERT(last != NULL); | 191 SkASSERT(last != nullptr); |
| 192 | 192 |
| 193 if (last->fEnd == NULL) { // we were marked empty from before | 193 if (last->fEnd == nullptr) { // we were marked empty from before |
| 194 last = last->fPrev; | 194 last = last->fPrev; |
| 195 last->fNext = NULL; | 195 last->fNext = nullptr; |
| 196 this->freeBlock(fBackBlock); | 196 this->freeBlock(fBackBlock); |
| 197 fBackBlock = last; | 197 fBackBlock = last; |
| 198 SkASSERT(last != NULL); // else we popped too far | 198 SkASSERT(last != nullptr); // else we popped too far |
| 199 } | 199 } |
| 200 | 200 |
| 201 char* end = last->fEnd - fElemSize; | 201 char* end = last->fEnd - fElemSize; |
| 202 SkASSERT(end >= last->fBegin); | 202 SkASSERT(end >= last->fBegin); |
| 203 | 203 |
| 204 if (end > last->fBegin) { | 204 if (end > last->fBegin) { |
| 205 last->fEnd = end; | 205 last->fEnd = end; |
| 206 SkASSERT(last->fEnd); | 206 SkASSERT(last->fEnd); |
| 207 fBack = last->fEnd - fElemSize; | 207 fBack = last->fEnd - fElemSize; |
| 208 } else { | 208 } else { |
| 209 last->fBegin = last->fEnd = NULL; // mark as empty | 209 last->fBegin = last->fEnd = nullptr; // mark as empty |
| 210 if (NULL == last->fPrev) { | 210 if (nullptr == last->fPrev) { |
| 211 fFront = fBack = NULL; | 211 fFront = fBack = nullptr; |
| 212 } else { | 212 } else { |
| 213 SkASSERT(last->fPrev->fEnd); | 213 SkASSERT(last->fPrev->fEnd); |
| 214 fBack = last->fPrev->fEnd - fElemSize; | 214 fBack = last->fPrev->fEnd - fElemSize; |
| 215 } | 215 } |
| 216 } | 216 } |
| 217 } | 217 } |
| 218 | 218 |
| 219 int SkDeque::numBlocksAllocated() const { | 219 int SkDeque::numBlocksAllocated() const { |
| 220 int numBlocks = 0; | 220 int numBlocks = 0; |
| 221 | 221 |
| 222 for (const Block* temp = fFrontBlock; temp; temp = temp->fNext) { | 222 for (const Block* temp = fFrontBlock; temp; temp = temp->fNext) { |
| 223 ++numBlocks; | 223 ++numBlocks; |
| 224 } | 224 } |
| 225 | 225 |
| 226 return numBlocks; | 226 return numBlocks; |
| 227 } | 227 } |
| 228 | 228 |
| 229 SkDeque::Block* SkDeque::allocateBlock(int allocCount) { | 229 SkDeque::Block* SkDeque::allocateBlock(int allocCount) { |
| 230 Block* newBlock = (Block*)sk_malloc_throw(sizeof(Block) + allocCount * fElem
Size); | 230 Block* newBlock = (Block*)sk_malloc_throw(sizeof(Block) + allocCount * fElem
Size); |
| 231 newBlock->init(sizeof(Block) + allocCount * fElemSize); | 231 newBlock->init(sizeof(Block) + allocCount * fElemSize); |
| 232 return newBlock; | 232 return newBlock; |
| 233 } | 233 } |
| 234 | 234 |
| 235 void SkDeque::freeBlock(Block* block) { | 235 void SkDeque::freeBlock(Block* block) { |
| 236 sk_free(block); | 236 sk_free(block); |
| 237 } | 237 } |
| 238 | 238 |
| 239 /////////////////////////////////////////////////////////////////////////////// | 239 /////////////////////////////////////////////////////////////////////////////// |
| 240 | 240 |
| 241 SkDeque::Iter::Iter() : fCurBlock(NULL), fPos(NULL), fElemSize(0) {} | 241 SkDeque::Iter::Iter() : fCurBlock(nullptr), fPos(nullptr), fElemSize(0) {} |
| 242 | 242 |
| 243 SkDeque::Iter::Iter(const SkDeque& d, IterStart startLoc) { | 243 SkDeque::Iter::Iter(const SkDeque& d, IterStart startLoc) { |
| 244 this->reset(d, startLoc); | 244 this->reset(d, startLoc); |
| 245 } | 245 } |
| 246 | 246 |
| 247 // Due to how reset and next work, next actually returns the current element | 247 // Due to how reset and next work, next actually returns the current element |
| 248 // pointed to by fPos and then updates fPos to point to the next one. | 248 // pointed to by fPos and then updates fPos to point to the next one. |
| 249 void* SkDeque::Iter::next() { | 249 void* SkDeque::Iter::next() { |
| 250 char* pos = fPos; | 250 char* pos = fPos; |
| 251 | 251 |
| 252 if (pos) { // if we were valid, try to move to the next setting | 252 if (pos) { // if we were valid, try to move to the next setting |
| 253 char* next = pos + fElemSize; | 253 char* next = pos + fElemSize; |
| 254 SkASSERT(next <= fCurBlock->fEnd); | 254 SkASSERT(next <= fCurBlock->fEnd); |
| 255 if (next == fCurBlock->fEnd) { // exhausted this chunk, move to next | 255 if (next == fCurBlock->fEnd) { // exhausted this chunk, move to next |
| 256 do { | 256 do { |
| 257 fCurBlock = fCurBlock->fNext; | 257 fCurBlock = fCurBlock->fNext; |
| 258 } while (fCurBlock != NULL && fCurBlock->fBegin == NULL); | 258 } while (fCurBlock != nullptr && fCurBlock->fBegin == nullptr); |
| 259 next = fCurBlock ? fCurBlock->fBegin : NULL; | 259 next = fCurBlock ? fCurBlock->fBegin : nullptr; |
| 260 } | 260 } |
| 261 fPos = next; | 261 fPos = next; |
| 262 } | 262 } |
| 263 return pos; | 263 return pos; |
| 264 } | 264 } |
| 265 | 265 |
| 266 // Like next, prev actually returns the current element pointed to by fPos and | 266 // Like next, prev actually returns the current element pointed to by fPos and |
| 267 // then makes fPos point to the previous element. | 267 // then makes fPos point to the previous element. |
| 268 void* SkDeque::Iter::prev() { | 268 void* SkDeque::Iter::prev() { |
| 269 char* pos = fPos; | 269 char* pos = fPos; |
| 270 | 270 |
| 271 if (pos) { // if we were valid, try to move to the prior setting | 271 if (pos) { // if we were valid, try to move to the prior setting |
| 272 char* prev = pos - fElemSize; | 272 char* prev = pos - fElemSize; |
| 273 SkASSERT(prev >= fCurBlock->fBegin - fElemSize); | 273 SkASSERT(prev >= fCurBlock->fBegin - fElemSize); |
| 274 if (prev < fCurBlock->fBegin) { // exhausted this chunk, move to prior | 274 if (prev < fCurBlock->fBegin) { // exhausted this chunk, move to prior |
| 275 do { | 275 do { |
| 276 fCurBlock = fCurBlock->fPrev; | 276 fCurBlock = fCurBlock->fPrev; |
| 277 } while (fCurBlock != NULL && fCurBlock->fEnd == NULL); | 277 } while (fCurBlock != nullptr && fCurBlock->fEnd == nullptr); |
| 278 prev = fCurBlock ? fCurBlock->fEnd - fElemSize : NULL; | 278 prev = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr; |
| 279 } | 279 } |
| 280 fPos = prev; | 280 fPos = prev; |
| 281 } | 281 } |
| 282 return pos; | 282 return pos; |
| 283 } | 283 } |
| 284 | 284 |
| 285 // reset works by skipping through the spare blocks at the start (or end) | 285 // reset works by skipping through the spare blocks at the start (or end) |
| 286 // of the doubly linked list until a non-empty one is found. The fPos | 286 // of the doubly linked list until a non-empty one is found. The fPos |
| 287 // member is then set to the first (or last) element in the block. If | 287 // member is then set to the first (or last) element in the block. If |
| 288 // there are no elements in the deque both fCurBlock and fPos will come | 288 // there are no elements in the deque both fCurBlock and fPos will come |
| 289 // out of this routine NULL. | 289 // out of this routine nullptr. |
| 290 void SkDeque::Iter::reset(const SkDeque& d, IterStart startLoc) { | 290 void SkDeque::Iter::reset(const SkDeque& d, IterStart startLoc) { |
| 291 fElemSize = d.fElemSize; | 291 fElemSize = d.fElemSize; |
| 292 | 292 |
| 293 if (kFront_IterStart == startLoc) { | 293 if (kFront_IterStart == startLoc) { |
| 294 // initialize the iterator to start at the front | 294 // initialize the iterator to start at the front |
| 295 fCurBlock = d.fFrontBlock; | 295 fCurBlock = d.fFrontBlock; |
| 296 while (fCurBlock && NULL == fCurBlock->fBegin) { | 296 while (fCurBlock && nullptr == fCurBlock->fBegin) { |
| 297 fCurBlock = fCurBlock->fNext; | 297 fCurBlock = fCurBlock->fNext; |
| 298 } | 298 } |
| 299 fPos = fCurBlock ? fCurBlock->fBegin : NULL; | 299 fPos = fCurBlock ? fCurBlock->fBegin : nullptr; |
| 300 } else { | 300 } else { |
| 301 // initialize the iterator to start at the back | 301 // initialize the iterator to start at the back |
| 302 fCurBlock = d.fBackBlock; | 302 fCurBlock = d.fBackBlock; |
| 303 while (fCurBlock && NULL == fCurBlock->fEnd) { | 303 while (fCurBlock && nullptr == fCurBlock->fEnd) { |
| 304 fCurBlock = fCurBlock->fPrev; | 304 fCurBlock = fCurBlock->fPrev; |
| 305 } | 305 } |
| 306 fPos = fCurBlock ? fCurBlock->fEnd - fElemSize : NULL; | 306 fPos = fCurBlock ? fCurBlock->fEnd - fElemSize : nullptr; |
| 307 } | 307 } |
| 308 } | 308 } |
| OLD | NEW |