OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2011 Google Inc. | 3 * Copyright 2011 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 | 10 |
11 #ifndef SkTLazy_DEFINED | 11 #ifndef SkTLazy_DEFINED |
12 #define SkTLazy_DEFINED | 12 #define SkTLazy_DEFINED |
13 | 13 |
14 #include "SkTypes.h" | 14 #include "SkTypes.h" |
15 #include <new> | 15 #include <new> |
16 | 16 |
| 17 template <typename T> class SkTLazy; |
| 18 template <typename T> void* operator new(size_t, SkTLazy<T>* lazy); |
| 19 |
17 /** | 20 /** |
18 * Efficient way to defer allocating/initializing a class until it is needed | 21 * Efficient way to defer allocating/initializing a class until it is needed |
19 * (if ever). | 22 * (if ever). |
20 */ | 23 */ |
21 template <typename T> class SkTLazy { | 24 template <typename T> class SkTLazy { |
22 public: | 25 public: |
23 SkTLazy() : fPtr(NULL) {} | 26 SkTLazy() : fPtr(NULL) {} |
24 | 27 |
25 explicit SkTLazy(const T* src) : fPtr(NULL) { | 28 explicit SkTLazy(const T* src) : fPtr(NULL) { |
26 if (src) { | 29 if (src) { |
(...skipping 10 matching lines...) Expand all Loading... |
37 } | 40 } |
38 | 41 |
39 ~SkTLazy() { | 42 ~SkTLazy() { |
40 if (this->isValid()) { | 43 if (this->isValid()) { |
41 fPtr->~T(); | 44 fPtr->~T(); |
42 } | 45 } |
43 } | 46 } |
44 | 47 |
45 /** | 48 /** |
46 * Return a pointer to a default-initialized instance of the class. If a | 49 * Return a pointer to a default-initialized instance of the class. If a |
47 * previous instance had been initialzied (either from init() or set()) it | 50 * previous instance had been initialized (either from init() or set()) it |
48 * will first be destroyed, so that a freshly initialized instance is | 51 * will first be destroyed, so that a freshly initialized instance is |
49 * always returned. | 52 * always returned. |
50 */ | 53 */ |
51 T* init() { | 54 T* init() { |
52 if (this->isValid()) { | 55 if (this->isValid()) { |
53 fPtr->~T(); | 56 fPtr->~T(); |
54 } | 57 } |
55 fPtr = new (SkTCast<T*>(fStorage)) T; | 58 fPtr = new (SkTCast<T*>(fStorage)) T; |
56 return fPtr; | 59 return fPtr; |
57 } | 60 } |
(...skipping 19 matching lines...) Expand all Loading... |
77 */ | 80 */ |
78 bool isValid() const { return NULL != fPtr; } | 81 bool isValid() const { return NULL != fPtr; } |
79 | 82 |
80 /** | 83 /** |
81 * Returns either NULL, or a copy of the object that was passed to | 84 * Returns either NULL, or a copy of the object that was passed to |
82 * set() or the constructor. | 85 * set() or the constructor. |
83 */ | 86 */ |
84 T* get() const { SkASSERT(this->isValid()); return fPtr; } | 87 T* get() const { SkASSERT(this->isValid()); return fPtr; } |
85 | 88 |
86 private: | 89 private: |
| 90 friend void* operator new<T>(size_t, SkTLazy* lazy); |
| 91 |
87 T* fPtr; // NULL or fStorage | 92 T* fPtr; // NULL or fStorage |
88 char fStorage[sizeof(T)]; | 93 char fStorage[sizeof(T)]; |
89 }; | 94 }; |
90 | 95 |
| 96 // Use the below macro (SkNEW_IN_TLAZY) rather than calling this directly |
| 97 template <typename T> void* operator new(size_t, SkTLazy<T>* lazy) { |
| 98 SkASSERT(!lazy->isValid()); |
| 99 lazy->fPtr = reinterpret_cast<T*>(lazy->fStorage); |
| 100 return lazy->fPtr; |
| 101 } |
| 102 |
| 103 // Skia doesn't use C++ exceptions but it may be compiled with them enabled. Hav
ing an op delete |
| 104 // to match the op new silences warnings about missing op delete when a construc
tor throws an |
| 105 // exception. |
| 106 template <typename T> void operator delete(void*, SkTLazy<T>) { SK_CRASH(); } |
| 107 |
| 108 // Use this to construct a T inside an SkTLazy using a non-default constructor. |
| 109 #define SkNEW_IN_TLAZY(tlazy_ptr, type_name, args) (new (tlazy_ptr) type_name ar
gs) |
| 110 |
91 /** | 111 /** |
92 * A helper built on top of SkTLazy to do copy-on-first-write. The object is ini
tialized | 112 * A helper built on top of SkTLazy to do copy-on-first-write. The object is ini
tialized |
93 * with a const pointer but provides a non-const pointer accessor. The first tim
e the | 113 * with a const pointer but provides a non-const pointer accessor. The first tim
e the |
94 * accessor is called (if ever) the object is cloned. | 114 * accessor is called (if ever) the object is cloned. |
95 * | 115 * |
96 * In the following example at most one copy of constThing is made: | 116 * In the following example at most one copy of constThing is made: |
97 * | 117 * |
98 * SkTCopyOnFirstWrite<Thing> thing(&constThing); | 118 * SkTCopyOnFirstWrite<Thing> thing(&constThing); |
99 * ... | 119 * ... |
100 * function_that_takes_a_const_thing_ptr(thing); // constThing is passed | 120 * function_that_takes_a_const_thing_ptr(thing); // constThing is passed |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 operator const T*() const { return fObj; } | 167 operator const T*() const { return fObj; } |
148 | 168 |
149 const T& operator *() const { return *fObj; } | 169 const T& operator *() const { return *fObj; } |
150 | 170 |
151 private: | 171 private: |
152 const T* fObj; | 172 const T* fObj; |
153 SkTLazy<T> fLazy; | 173 SkTLazy<T> fLazy; |
154 }; | 174 }; |
155 | 175 |
156 #endif | 176 #endif |
OLD | NEW |