Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright 2011 Google Inc. | 2 * Copyright 2011 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #ifndef SkTArray_DEFINED | 8 #ifndef SkTArray_DEFINED |
| 9 #define SkTArray_DEFINED | 9 #define SkTArray_DEFINED |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 fAllocCount = 0; | 31 fAllocCount = 0; |
| 32 fMemArray = NULL; | 32 fMemArray = NULL; |
| 33 fPreAllocMemArray = NULL; | 33 fPreAllocMemArray = NULL; |
| 34 } | 34 } |
| 35 | 35 |
| 36 /** | 36 /** |
| 37 * Creates an empty array that will preallocate space for reserveCount | 37 * Creates an empty array that will preallocate space for reserveCount |
| 38 * elements. | 38 * elements. |
| 39 */ | 39 */ |
| 40 explicit SkTArray(int reserveCount) { | 40 explicit SkTArray(int reserveCount) { |
| 41 this->init(NULL, 0, NULL, reserveCount); | 41 this->init(0, NULL, reserveCount); |
| 42 } | 42 } |
| 43 | 43 |
| 44 /** | 44 /** |
| 45 * Copies one array to another. The new array will be heap allocated. | 45 * Copies one array to another. The new array will be heap allocated. |
| 46 */ | 46 */ |
| 47 explicit SkTArray(const SkTArray& array) { | 47 explicit SkTArray(const SkTArray& that) { |
| 48 this->init(array.fItemArray, array.fCount, NULL, 0); | 48 this->init(that.fCount, NULL, 0); |
| 49 this->copy(that.fItemArray); | |
| 50 } | |
| 51 explicit SkTArray(SkTArray&& that) { | |
| 52 this->init(that.fCount, NULL, 0); | |
| 53 that.move(fMemArray); | |
| 54 that.fCount = 0; | |
| 49 } | 55 } |
| 50 | 56 |
| 51 /** | 57 /** |
| 52 * Creates a SkTArray by copying contents of a standard C array. The new | 58 * Creates a SkTArray by copying contents of a standard C array. The new |
| 53 * array will be heap allocated. Be careful not to use this constructor | 59 * array will be heap allocated. Be careful not to use this constructor |
| 54 * when you really want the (void*, int) version. | 60 * when you really want the (void*, int) version. |
| 55 */ | 61 */ |
| 56 SkTArray(const T* array, int count) { | 62 SkTArray(const T* array, int count) { |
| 57 this->init(array, count, NULL, 0); | 63 this->init(count, NULL, 0); |
| 64 this->copy(array); | |
| 58 } | 65 } |
| 59 | 66 |
| 60 /** | 67 /** |
| 61 * assign copy of array to this | 68 * assign copy of array to this |
| 62 */ | 69 */ |
| 63 SkTArray& operator =(const SkTArray& array) { | 70 SkTArray& operator =(const SkTArray& that) { |
| 64 for (int i = 0; i < fCount; ++i) { | 71 for (int i = 0; i < fCount; ++i) { |
| 65 fItemArray[i].~T(); | 72 fItemArray[i].~T(); |
| 66 } | 73 } |
| 67 fCount = 0; | 74 fCount = 0; |
| 68 this->checkRealloc((int)array.count()); | 75 this->checkRealloc(that.count()); |
| 69 fCount = array.count(); | 76 fCount = that.count(); |
| 70 this->copy(static_cast<const T*>(array.fMemArray)); | 77 this->copy(that.fItemArray); |
| 78 return *this; | |
| 79 } | |
| 80 SkTArray& operator =(SkTArray&& that) { | |
| 81 for (int i = 0; i < fCount; ++i) { | |
| 82 fItemArray[i].~T(); | |
| 83 } | |
| 84 fCount = 0; | |
| 85 this->checkRealloc(that.count()); | |
| 86 fCount = that.count(); | |
| 87 that.move(fMemArray); | |
| 88 that.fCount = 0; | |
| 71 return *this; | 89 return *this; |
| 72 } | 90 } |
| 73 | 91 |
| 74 ~SkTArray() { | 92 ~SkTArray() { |
| 75 for (int i = 0; i < fCount; ++i) { | 93 for (int i = 0; i < fCount; ++i) { |
| 76 fItemArray[i].~T(); | 94 fItemArray[i].~T(); |
| 77 } | 95 } |
| 78 if (fMemArray != fPreAllocMemArray) { | 96 if (fMemArray != fPreAllocMemArray) { |
| 79 sk_free(fMemArray); | 97 sk_free(fMemArray); |
| 80 } | 98 } |
| 81 } | 99 } |
| 82 | 100 |
| 83 /** | 101 /** |
| 84 * Resets to count() == 0 | 102 * Resets to count() == 0 |
| 85 */ | 103 */ |
| 86 void reset() { this->pop_back_n(fCount); } | 104 void reset() { this->pop_back_n(fCount); } |
| 87 | 105 |
| 88 /** | 106 /** |
| 89 * Resets to count() = n newly constructed T objects. | 107 * Resets to count() = n newly constructed T objects. |
| 90 */ | 108 */ |
| 91 void reset(int n) { | 109 void reset(int n) { |
| 92 SkASSERT(n >= 0); | 110 SkASSERT(n >= 0); |
| 93 for (int i = 0; i < fCount; ++i) { | 111 for (int i = 0; i < fCount; ++i) { |
| 94 fItemArray[i].~T(); | 112 fItemArray[i].~T(); |
| 95 } | 113 } |
| 96 // set fCount to 0 before calling checkRealloc so that no copy cons. are called. | 114 // Set fCount to 0 before calling checkRealloc so that no elements are m oved. |
| 97 fCount = 0; | 115 fCount = 0; |
| 98 this->checkRealloc(n); | 116 this->checkRealloc(n); |
| 99 fCount = n; | 117 fCount = n; |
| 100 for (int i = 0; i < fCount; ++i) { | 118 for (int i = 0; i < fCount; ++i) { |
| 101 new (fItemArray + i) T; | 119 new (fItemArray + i) T; |
| 102 } | 120 } |
| 103 } | 121 } |
| 104 | 122 |
| 105 /** | 123 /** |
| 106 * Resets to a copy of a C array. | 124 * Resets to a copy of a C array. |
| 107 */ | 125 */ |
| 108 void reset(const T* array, int count) { | 126 void reset(const T* array, int count) { |
| 109 for (int i = 0; i < fCount; ++i) { | 127 for (int i = 0; i < fCount; ++i) { |
| 110 fItemArray[i].~T(); | 128 fItemArray[i].~T(); |
| 111 } | 129 } |
| 112 int delta = count - fCount; | 130 fCount = 0; |
| 113 this->checkRealloc(delta); | 131 this->checkRealloc(count); |
| 114 fCount = count; | 132 fCount = count; |
| 115 this->copy(array); | 133 this->copy(array); |
| 116 } | 134 } |
| 117 | 135 |
| 118 void removeShuffle(int n) { | 136 void removeShuffle(int n) { |
| 119 SkASSERT(n < fCount); | 137 SkASSERT(n < fCount); |
| 120 int newCount = fCount - 1; | 138 int newCount = fCount - 1; |
| 121 fCount = newCount; | 139 fCount = newCount; |
| 122 fItemArray[n].~T(); | 140 fItemArray[n].~T(); |
| 123 if (n != newCount) { | 141 if (n != newCount) { |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 256 if (this == that) { | 274 if (this == that) { |
| 257 return; | 275 return; |
| 258 } | 276 } |
| 259 if (this->fPreAllocMemArray != this->fItemArray && | 277 if (this->fPreAllocMemArray != this->fItemArray && |
| 260 that->fPreAllocMemArray != that->fItemArray) { | 278 that->fPreAllocMemArray != that->fItemArray) { |
| 261 // If neither is using a preallocated array then just swap. | 279 // If neither is using a preallocated array then just swap. |
| 262 SkTSwap(fItemArray, that->fItemArray); | 280 SkTSwap(fItemArray, that->fItemArray); |
| 263 SkTSwap(fCount, that->fCount); | 281 SkTSwap(fCount, that->fCount); |
| 264 SkTSwap(fAllocCount, that->fAllocCount); | 282 SkTSwap(fAllocCount, that->fAllocCount); |
| 265 } else { | 283 } else { |
| 266 // This could be more optimal... | 284 // This could be more optimal... |
|
mtklein
2016/04/20 15:50:44
Still true?
bungeman-skia
2016/04/20 17:21:12
It could be. We could avoid dome destructor/constr
| |
| 267 SkTArray copy(*that); | 285 SkTArray copy(std::move(*that)); |
| 268 *that = *this; | 286 *that = std::move(*this); |
| 269 *this = copy; | 287 *this = std::move(copy); |
| 270 } | 288 } |
| 271 } | 289 } |
| 272 | 290 |
| 273 T* begin() { | 291 T* begin() { |
| 274 return fItemArray; | 292 return fItemArray; |
| 275 } | 293 } |
| 276 const T* begin() const { | 294 const T* begin() const { |
| 277 return fItemArray; | 295 return fItemArray; |
| 278 } | 296 } |
| 279 T* end() { | 297 T* end() { |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 344 return !(*this == right); | 362 return !(*this == right); |
| 345 } | 363 } |
| 346 | 364 |
| 347 protected: | 365 protected: |
| 348 /** | 366 /** |
| 349 * Creates an empty array that will use the passed storage block until it | 367 * Creates an empty array that will use the passed storage block until it |
| 350 * is insufficiently large to hold the entire array. | 368 * is insufficiently large to hold the entire array. |
| 351 */ | 369 */ |
| 352 template <int N> | 370 template <int N> |
| 353 SkTArray(SkAlignedSTStorage<N,T>* storage) { | 371 SkTArray(SkAlignedSTStorage<N,T>* storage) { |
| 354 this->init(NULL, 0, storage->get(), N); | 372 this->init(0, storage->get(), N); |
| 355 } | 373 } |
| 356 | 374 |
| 357 /** | 375 /** |
| 358 * Copy another array, using preallocated storage if preAllocCount >= | 376 * Copy another array, using preallocated storage if preAllocCount >= |
| 359 * array.count(). Otherwise storage will only be used when array shrinks | 377 * array.count(). Otherwise storage will only be used when array shrinks |
| 360 * to fit. | 378 * to fit. |
| 361 */ | 379 */ |
| 362 template <int N> | 380 template <int N> |
| 363 SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) { | 381 SkTArray(const SkTArray& array, SkAlignedSTStorage<N,T>* storage) { |
| 364 this->init(array.fItemArray, array.fCount, storage->get(), N); | 382 this->init(array.fCount, storage->get(), N); |
| 383 this->copy(array.fItemArray); | |
| 365 } | 384 } |
| 366 | 385 |
| 367 /** | 386 /** |
| 368 * Copy a C array, using preallocated storage if preAllocCount >= | 387 * Copy a C array, using preallocated storage if preAllocCount >= |
| 369 * count. Otherwise storage will only be used when array shrinks | 388 * count. Otherwise storage will only be used when array shrinks |
| 370 * to fit. | 389 * to fit. |
| 371 */ | 390 */ |
| 372 template <int N> | 391 template <int N> |
| 373 SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) { | 392 SkTArray(const T* array, int count, SkAlignedSTStorage<N,T>* storage) { |
| 374 this->init(array, count, storage->get(), N); | 393 this->init(count, storage->get(), N); |
| 394 this->copy(array); | |
| 375 } | 395 } |
| 376 | 396 |
| 377 void init(const T* array, int count, | 397 void init(int count, void* preAllocStorage, int preAllocOrReserveCount) { |
| 378 void* preAllocStorage, int preAllocOrReserveCount) { | |
| 379 SkASSERT(count >= 0); | 398 SkASSERT(count >= 0); |
| 380 SkASSERT(preAllocOrReserveCount >= 0); | 399 SkASSERT(preAllocOrReserveCount >= 0); |
| 381 fCount = count; | 400 fCount = count; |
| 382 fReserveCount = (preAllocOrReserveCount > 0) ? | 401 fReserveCount = (preAllocOrReserveCount > 0) ? |
| 383 preAllocOrReserveCount : | 402 preAllocOrReserveCount : |
| 384 gMIN_ALLOC_COUNT; | 403 gMIN_ALLOC_COUNT; |
| 385 fPreAllocMemArray = preAllocStorage; | 404 fPreAllocMemArray = preAllocStorage; |
| 386 if (fReserveCount >= fCount && | 405 if (fReserveCount >= fCount && |
| 387 preAllocStorage) { | 406 preAllocStorage) { |
| 388 fAllocCount = fReserveCount; | 407 fAllocCount = fReserveCount; |
| 389 fMemArray = preAllocStorage; | 408 fMemArray = preAllocStorage; |
| 390 } else { | 409 } else { |
| 391 fAllocCount = SkMax32(fCount, fReserveCount); | 410 fAllocCount = SkMax32(fCount, fReserveCount); |
| 392 fMemArray = sk_malloc_throw(fAllocCount * sizeof(T)); | 411 fMemArray = sk_malloc_throw(fAllocCount * sizeof(T)); |
| 393 } | 412 } |
| 394 | |
| 395 this->copy(array); | |
| 396 } | 413 } |
| 397 | 414 |
| 398 private: | 415 private: |
| 399 /** In the following move and copy methods, 'dst' is assumed to be uninitial ized raw storage. | 416 /** In the following move and copy methods, 'dst' is assumed to be uninitial ized raw storage. |
| 400 * In the following move methods, 'src' is destroyed leaving behind uniniti alized raw storage. | 417 * In the following move methods, 'src' is destroyed leaving behind uniniti alized raw storage. |
| 401 */ | 418 */ |
| 402 template <bool E = MEM_COPY> SK_WHEN(E, void) copy(const T* src) { | 419 template <bool E = MEM_COPY> SK_WHEN(E, void) copy(const T* src) { |
| 403 sk_careful_memcpy(fMemArray, src, fCount * sizeof(T)); | 420 sk_careful_memcpy(fMemArray, src, fCount * sizeof(T)); |
| 404 } | 421 } |
| 405 template <bool E = MEM_COPY> SK_WHEN(E, void) move(int dst, int src) { | 422 template <bool E = MEM_COPY> SK_WHEN(E, void) move(int dst, int src) { |
| 406 memcpy(&fItemArray[dst], &fItemArray[src], sizeof(T)); | 423 memcpy(&fItemArray[dst], &fItemArray[src], sizeof(T)); |
| 407 } | 424 } |
| 408 template <bool E = MEM_COPY> SK_WHEN(E, void) move(char* dst) { | 425 template <bool E = MEM_COPY> SK_WHEN(E, void) move(void* dst) { |
| 409 sk_careful_memcpy(dst, fMemArray, fCount * sizeof(T)); | 426 sk_careful_memcpy(dst, fMemArray, fCount * sizeof(T)); |
| 410 } | 427 } |
| 411 | 428 |
| 412 template <bool E = MEM_COPY> SK_WHEN(!E, void) copy(const T* src) { | 429 template <bool E = MEM_COPY> SK_WHEN(!E, void) copy(const T* src) { |
| 413 for (int i = 0; i < fCount; ++i) { | 430 for (int i = 0; i < fCount; ++i) { |
| 414 new (fItemArray + i) T(src[i]); | 431 new (fItemArray + i) T(src[i]); |
| 415 } | 432 } |
| 416 } | 433 } |
| 417 template <bool E = MEM_COPY> SK_WHEN(!E, void) move(int dst, int src) { | 434 template <bool E = MEM_COPY> SK_WHEN(!E, void) move(int dst, int src) { |
| 418 new (&fItemArray[dst]) T(std::move(fItemArray[src])); | 435 new (&fItemArray[dst]) T(std::move(fItemArray[src])); |
| 419 fItemArray[src].~T(); | 436 fItemArray[src].~T(); |
| 420 } | 437 } |
| 421 template <bool E = MEM_COPY> SK_WHEN(!E, void) move(char* dst) { | 438 template <bool E = MEM_COPY> SK_WHEN(!E, void) move(void* dst) { |
| 422 for (int i = 0; i < fCount; ++i) { | 439 for (int i = 0; i < fCount; ++i) { |
| 423 new (dst + sizeof(T) * i) T(std::move(fItemArray[i])); | 440 new (static_cast<char*>(dst) + sizeof(T) * i) T(std::move(fItemArray [i])); |
| 424 fItemArray[i].~T(); | 441 fItemArray[i].~T(); |
| 425 } | 442 } |
| 426 } | 443 } |
| 427 | 444 |
| 428 static const int gMIN_ALLOC_COUNT = 8; | 445 static const int gMIN_ALLOC_COUNT = 8; |
| 429 | 446 |
| 430 // Helper function that makes space for n objects, adjusts the count, but do es not initialize | 447 // Helper function that makes space for n objects, adjusts the count, but do es not initialize |
| 431 // the new objects. | 448 // the new objects. |
| 432 void* push_back_raw(int n) { | 449 void* push_back_raw(int n) { |
| 433 this->checkRealloc(n); | 450 this->checkRealloc(n); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 446 int newAllocCount = fAllocCount; | 463 int newAllocCount = fAllocCount; |
| 447 | 464 |
| 448 if (newCount > fAllocCount || newCount < (fAllocCount / 3)) { | 465 if (newCount > fAllocCount || newCount < (fAllocCount / 3)) { |
| 449 // whether we're growing or shrinking, we leave at least 50% extra s pace for future | 466 // whether we're growing or shrinking, we leave at least 50% extra s pace for future |
| 450 // growth (clamped to the reserve count). | 467 // growth (clamped to the reserve count). |
| 451 newAllocCount = SkMax32(newCount + ((newCount + 1) >> 1), fReserveCo unt); | 468 newAllocCount = SkMax32(newCount + ((newCount + 1) >> 1), fReserveCo unt); |
| 452 } | 469 } |
| 453 if (newAllocCount != fAllocCount) { | 470 if (newAllocCount != fAllocCount) { |
| 454 | 471 |
| 455 fAllocCount = newAllocCount; | 472 fAllocCount = newAllocCount; |
| 456 char* newMemArray; | 473 void* newMemArray; |
| 457 | 474 |
| 458 if (fAllocCount == fReserveCount && fPreAllocMemArray) { | 475 if (fAllocCount == fReserveCount && fPreAllocMemArray) { |
| 459 newMemArray = (char*) fPreAllocMemArray; | 476 newMemArray = fPreAllocMemArray; |
| 460 } else { | 477 } else { |
| 461 newMemArray = (char*) sk_malloc_throw(fAllocCount*sizeof(T)); | 478 newMemArray = sk_malloc_throw(fAllocCount*sizeof(T)); |
| 462 } | 479 } |
| 463 | 480 |
| 464 this->move(newMemArray); | 481 this->move(newMemArray); |
| 465 | 482 |
| 466 if (fMemArray != fPreAllocMemArray) { | 483 if (fMemArray != fPreAllocMemArray) { |
| 467 sk_free(fMemArray); | 484 sk_free(fMemArray); |
| 468 } | 485 } |
| 469 fMemArray = newMemArray; | 486 fMemArray = newMemArray; |
| 470 } | 487 } |
| 471 } | 488 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 515 SkSTArray& operator= (const INHERITED& array) { | 532 SkSTArray& operator= (const INHERITED& array) { |
| 516 INHERITED::operator=(array); | 533 INHERITED::operator=(array); |
| 517 return *this; | 534 return *this; |
| 518 } | 535 } |
| 519 | 536 |
| 520 private: | 537 private: |
| 521 SkAlignedSTStorage<N,T> fStorage; | 538 SkAlignedSTStorage<N,T> fStorage; |
| 522 }; | 539 }; |
| 523 | 540 |
| 524 #endif | 541 #endif |
| OLD | NEW |