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 |