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