1 2/* 3 * Copyright 2011 Google Inc. 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10 11#ifndef SkTLazy_DEFINED 12#define SkTLazy_DEFINED 13 14#include "SkTypes.h" 15#include <new> 16 17/** 18 * Efficient way to defer allocating/initializing a class until it is needed 19 * (if ever). 20 */ 21template <typename T> class SkTLazy { 22public: 23 SkTLazy() : fPtr(NULL) {} 24 25 explicit SkTLazy(const T* src) : fPtr(NULL) { 26 if (src) { 27 fPtr = new (fStorage) T(*src); 28 } 29 } 30 31 SkTLazy(const SkTLazy<T>& src) : fPtr(NULL) { 32 if (src.isValid()) { 33 fPtr = new (fStorage) T(*src->get()); 34 } else { 35 fPtr = NULL; 36 } 37 } 38 39 ~SkTLazy() { 40 if (this->isValid()) { 41 fPtr->~T(); 42 } 43 } 44 45 /** 46 * 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 48 * will first be destroyed, so that a freshly initialized instance is 49 * always returned. 50 */ 51 T* init() { 52 if (this->isValid()) { 53 fPtr->~T(); 54 } 55 fPtr = new (SkTCast<T*>(fStorage)) T; 56 return fPtr; 57 } 58 59 /** 60 * Copy src into this, and return a pointer to a copy of it. Note this 61 * will always return the same pointer, so if it is called on a lazy that 62 * has already been initialized, then this will copy over the previous 63 * contents. 64 */ 65 T* set(const T& src) { 66 if (this->isValid()) { 67 *fPtr = src; 68 } else { 69 fPtr = new (SkTCast<T*>(fStorage)) T(src); 70 } 71 return fPtr; 72 } 73 74 /** 75 * Returns true if a valid object has been initialized in the SkTLazy, 76 * false otherwise. 77 */ 78 bool isValid() const { return NULL != fPtr; } 79 80 /** 81 * Returns either NULL, or a copy of the object that was passed to 82 * set() or the constructor. 83 */ 84 T* get() const { SkASSERT(this->isValid()); return fPtr; } 85 86private: 87 T* fPtr; // NULL or fStorage 88 char fStorage[sizeof(T)]; 89}; 90 91#endif 92 93