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