• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
Alloc(int count)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      */
Create(int count)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      */
Create(const T src[],int count)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 
count()64     int count() const { return fCount; }
begin()65     const T* begin() const { return (const T*)(this + 1); }
end()66     const T* end() const { return this->begin() + fCount; }
at(int index)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 
writableBegin()76     T* writableBegin() {
77         SkASSERT(this->unique());
78         return (T*)(this + 1);
79     }
writableEnd()80     T* writableEnd() {
81         return this->writableBegin() + fCount;
82     }
writableAt(int index)83     T& writableAt(int index) {
84         SkASSERT((unsigned)index < (unsigned)fCount);
85         return this->writableBegin()[index];
86     }
87 
88 protected:
internal_dispose()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
~SkTRefArray()107     virtual ~SkTRefArray() {}
108 
109     typedef SkRefCnt INHERITED;
110 };
111 
112 #endif
113