OLD | NEW |
| (Empty) |
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 | |
OLD | NEW |