| 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 |