Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(114)

Side by Side Diff: include/private/SkTArray.h

Issue 1904663004: SkTArray movable and swap for move only elements. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 4 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | tests/TArrayTest.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | tests/TArrayTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698