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 SkTLazy_DEFINED | 8 #ifndef SkTLazy_DEFINED |
9 #define SkTLazy_DEFINED | 9 #define SkTLazy_DEFINED |
10 | 10 |
11 #include "../private/SkTemplates.h" | 11 #include "../private/SkTemplates.h" |
12 #include "SkTypes.h" | 12 #include "SkTypes.h" |
13 #include <new> | 13 #include <new> |
14 #include <utility> | 14 #include <utility> |
15 | 15 |
16 /** | 16 /** |
17 * Efficient way to defer allocating/initializing a class until it is needed | 17 * Efficient way to defer allocating/initializing a class until it is needed |
18 * (if ever). | 18 * (if ever). |
19 */ | 19 */ |
20 template <typename T> class SkTLazy { | 20 template <typename T> class SkTLazy { |
21 public: | 21 public: |
22 SkTLazy() : fPtr(NULL) {} | 22 SkTLazy() : fPtr(nullptr) {} |
23 | 23 |
24 explicit SkTLazy(const T* src) : fPtr(NULL) { | 24 explicit SkTLazy(const T* src) |
25 if (src) { | 25 : fPtr(src ? new (fStorage.get()) T(*src) : nullptr) {} |
26 fPtr = new (fStorage.get()) T(*src); | |
27 } | |
28 } | |
29 | 26 |
30 SkTLazy(const SkTLazy<T>& src) : fPtr(NULL) { | 27 SkTLazy(const SkTLazy& src) : fPtr(nullptr) { *this = src; } |
31 if (src.isValid()) { | |
32 fPtr = new (fStorage.get()) T(*src.get()); | |
33 } else { | |
34 fPtr = NULL; | |
35 } | |
36 } | |
37 | 28 |
38 ~SkTLazy() { | 29 ~SkTLazy() { |
39 if (this->isValid()) { | 30 if (this->isValid()) { |
40 fPtr->~T(); | 31 fPtr->~T(); |
41 } | 32 } |
42 } | 33 } |
43 | 34 |
| 35 SkTLazy& operator=(const SkTLazy& src) { |
| 36 if (src.isValid()) { |
| 37 this->set(*src.get()); |
| 38 } else { |
| 39 this->reset(); |
| 40 } |
| 41 return *this; |
| 42 } |
| 43 |
44 /** | 44 /** |
45 * Return a pointer to an instance of the class initialized with 'args'. | 45 * Return a pointer to an instance of the class initialized with 'args'. |
46 * If a previous instance had been initialized (either from init() or | 46 * If a previous instance had been initialized (either from init() or |
47 * set()) it will first be destroyed, so that a freshly initialized | 47 * set()) it will first be destroyed, so that a freshly initialized |
48 * instance is always returned. | 48 * instance is always returned. |
49 */ | 49 */ |
50 template <typename... Args> T* init(Args&&... args) { | 50 template <typename... Args> T* init(Args&&... args) { |
51 if (this->isValid()) { | 51 if (this->isValid()) { |
52 fPtr->~T(); | 52 fPtr->~T(); |
53 } | 53 } |
(...skipping 15 matching lines...) Expand all Loading... |
69 } | 69 } |
70 return fPtr; | 70 return fPtr; |
71 } | 71 } |
72 | 72 |
73 /** | 73 /** |
74 * Destroy the lazy object (if it was created via init() or set()) | 74 * Destroy the lazy object (if it was created via init() or set()) |
75 */ | 75 */ |
76 void reset() { | 76 void reset() { |
77 if (this->isValid()) { | 77 if (this->isValid()) { |
78 fPtr->~T(); | 78 fPtr->~T(); |
79 fPtr = NULL; | 79 fPtr = nullptr; |
80 } | 80 } |
81 } | 81 } |
82 | 82 |
83 /** | 83 /** |
84 * Returns true if a valid object has been initialized in the SkTLazy, | 84 * Returns true if a valid object has been initialized in the SkTLazy, |
85 * false otherwise. | 85 * false otherwise. |
86 */ | 86 */ |
87 bool isValid() const { return SkToBool(fPtr); } | 87 bool isValid() const { return SkToBool(fPtr); } |
88 | 88 |
89 /** | 89 /** |
90 * Returns the object. This version should only be called when the caller | 90 * Returns the object. This version should only be called when the caller |
91 * knows that the object has been initialized. | 91 * knows that the object has been initialized. |
92 */ | 92 */ |
93 T* get() const { SkASSERT(this->isValid()); return fPtr; } | 93 T* get() const { SkASSERT(this->isValid()); return fPtr; } |
94 | 94 |
95 /** | 95 /** |
96 * Like above but doesn't assert if object isn't initialized (in which case | 96 * Like above but doesn't assert if object isn't initialized (in which case |
97 * NULL is returned). | 97 * nullptr is returned). |
98 */ | 98 */ |
99 T* getMaybeNull() const { return fPtr; } | 99 T* getMaybeNull() const { return fPtr; } |
100 | 100 |
101 private: | 101 private: |
102 T* fPtr; // NULL or fStorage | 102 T* fPtr; // nullptr or fStorage |
103 SkAlignedSTStorage<1, T> fStorage; | 103 SkAlignedSTStorage<1, T> fStorage; |
104 }; | 104 }; |
105 | 105 |
106 /** | 106 /** |
107 * A helper built on top of SkTLazy to do copy-on-first-write. The object is ini
tialized | 107 * A helper built on top of SkTLazy to do copy-on-first-write. The object is ini
tialized |
108 * with a const pointer but provides a non-const pointer accessor. The first tim
e the | 108 * with a const pointer but provides a non-const pointer accessor. The first tim
e the |
109 * accessor is called (if ever) the object is cloned. | 109 * accessor is called (if ever) the object is cloned. |
110 * | 110 * |
111 * In the following example at most one copy of constThing is made: | 111 * In the following example at most one copy of constThing is made: |
112 * | 112 * |
(...skipping 14 matching lines...) Expand all Loading... |
127 * consume_a_thing(thing); // could be constThing or a modified copy. | 127 * consume_a_thing(thing); // could be constThing or a modified copy. |
128 */ | 128 */ |
129 template <typename T> | 129 template <typename T> |
130 class SkTCopyOnFirstWrite { | 130 class SkTCopyOnFirstWrite { |
131 public: | 131 public: |
132 SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {} | 132 SkTCopyOnFirstWrite(const T& initial) : fObj(&initial) {} |
133 | 133 |
134 SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {} | 134 SkTCopyOnFirstWrite(const T* initial) : fObj(initial) {} |
135 | 135 |
136 // Constructor for delayed initialization. | 136 // Constructor for delayed initialization. |
137 SkTCopyOnFirstWrite() : fObj(NULL) {} | 137 SkTCopyOnFirstWrite() : fObj(nullptr) {} |
138 | 138 |
139 // Should only be called once, and only if the default constructor was used. | 139 // Should only be called once, and only if the default constructor was used. |
140 void init(const T& initial) { | 140 void init(const T& initial) { |
141 SkASSERT(NULL == fObj); | 141 SkASSERT(nullptr == fObj); |
142 SkASSERT(!fLazy.isValid()); | 142 SkASSERT(!fLazy.isValid()); |
143 fObj = &initial; | 143 fObj = &initial; |
144 } | 144 } |
145 | 145 |
146 /** | 146 /** |
147 * Returns a writable T*. The first time this is called the initial object i
s cloned. | 147 * Returns a writable T*. The first time this is called the initial object i
s cloned. |
148 */ | 148 */ |
149 T* writable() { | 149 T* writable() { |
150 SkASSERT(fObj); | 150 SkASSERT(fObj); |
151 if (!fLazy.isValid()) { | 151 if (!fLazy.isValid()) { |
(...skipping 12 matching lines...) Expand all Loading... |
164 operator const T*() const { return fObj; } | 164 operator const T*() const { return fObj; } |
165 | 165 |
166 const T& operator *() const { return *fObj; } | 166 const T& operator *() const { return *fObj; } |
167 | 167 |
168 private: | 168 private: |
169 const T* fObj; | 169 const T* fObj; |
170 SkTLazy<T> fLazy; | 170 SkTLazy<T> fLazy; |
171 }; | 171 }; |
172 | 172 |
173 #endif | 173 #endif |
OLD | NEW |