1 // 2 // SkTRefArray.h 3 // core 4 // 5 // Created by Mike Reed on 7/17/12. 6 // Copyright (c) 2012 __MyCompanyName__. All rights reserved. 7 // 8 9 #ifndef SkTRefArray_DEFINED 10 #define SkTRefArray_DEFINED 11 12 #include "SkRefCnt.h" 13 #include <new> 14 15 /** 16 * Wrapper to manage thread-safe sharing of an array of T objects. The array 17 * cannot be grown or shrunk. 18 */ 19 template <typename T> class SkTRefArray : public SkRefCnt { 20 /* 21 * Shared factory to allocate the space needed for our instance plus N 22 * T entries at the end. We call our constructor, but not the constructors 23 * for the elements. Those are called by the proper Create method. 24 */ 25 static SkTRefArray<T>* Alloc(int count) { 26 // space for us, and our [count] elements 27 size_t size = sizeof(SkTRefArray<T>) + count * sizeof(T); 28 SkTRefArray<T>* obj = (SkTRefArray<T>*)sk_malloc_throw(size); 29 30 SkNEW_PLACEMENT(obj, SkTRefArray<T>); 31 obj->fCount = count; 32 return obj; 33 } 34 35 public: 36 /** 37 * Return a new array with 'count' elements, initialized to their default 38 * value. To change them to some other value, use writableBegin/End or 39 * writableAt(), but do that before this array is given to another thread. 40 */ 41 static SkTRefArray<T>* Create(int count) { 42 SkTRefArray<T>* obj = Alloc(count); 43 T* array = const_cast<T*>(obj->begin()); 44 for (int i = 0; i < count; ++i) { 45 SkNEW_PLACEMENT(&array[i], T); 46 } 47 return obj; 48 } 49 50 /** 51 * Return a new array with 'count' elements, initialized from the provided 52 * src array. To change them to some other value, use writableBegin/End or 53 * writableAt(), but do that before this array is given to another thread. 54 */ 55 static SkTRefArray<T>* Create(const T src[], int count) { 56 SkTRefArray<T>* obj = Alloc(count); 57 T* array = const_cast<T*>(obj->begin()); 58 for (int i = 0; i < count; ++i) { 59 SkNEW_PLACEMENT_ARGS(&array[i], T, (src[i])); 60 } 61 return obj; 62 } 63 64 int count() const { return fCount; } 65 const T* begin() const { return (const T*)(this + 1); } 66 const T* end() const { return this->begin() + fCount; } 67 const T& at(int index) const { 68 SkASSERT((unsigned)index < (unsigned)fCount); 69 return this->begin()[index]; 70 } 71 const T& operator[](int index) const { return this->at(index); } 72 73 // For the writable methods, we assert that we are the only owner if we 74 // call these, since other owners are not informed if we change an element. 75 76 T* writableBegin() { 77 SkASSERT(this->unique()); 78 return (T*)(this + 1); 79 } 80 T* writableEnd() { 81 return this->writableBegin() + fCount; 82 } 83 T& writableAt(int index) { 84 SkASSERT((unsigned)index < (unsigned)fCount); 85 return this->writableBegin()[index]; 86 } 87 88 protected: 89 virtual void internal_dispose() const SK_OVERRIDE { 90 T* array = const_cast<T*>(this->begin()); 91 int n = fCount; 92 93 for (int i = 0; i < n; ++i) { 94 array->~T(); 95 array += 1; 96 } 97 98 this->internal_dispose_restore_refcnt_to_1(); 99 this->~SkTRefArray<T>(); 100 sk_free((void*)this); 101 } 102 103 private: 104 int fCount; 105 106 // hide this 107 virtual ~SkTRefArray() {} 108 109 typedef SkRefCnt INHERITED; 110 }; 111 112 #endif 113