• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #ifndef SkTemplates_DEFINED
18 #define SkTemplates_DEFINED
19 
20 #include "SkTypes.h"
21 
22 /** \file SkTemplates.h
23 
24     This file contains light-weight template classes for type-safe and exception-safe
25     resource management.
26 */
27 
28 /** \class SkAutoTCallVProc
29 
30     Call a function when this goes out of scope. The template uses two
31     parameters, the object, and a function that is to be called in the destructor.
32     If detach() is called, the object reference is set to null. If the object
33     reference is null when the destructor is called, we do not call the
34     function.
35 */
36 template <typename T, void (*P)(T*)> class SkAutoTCallVProc : SkNoncopyable {
37 public:
SkAutoTCallVProc(T * obj)38     SkAutoTCallVProc(T* obj): fObj(obj) {}
~SkAutoTCallVProc()39     ~SkAutoTCallVProc() { if (fObj) P(fObj); }
detach()40     T* detach() { T* obj = fObj; fObj = NULL; return obj; }
41 private:
42     T* fObj;
43 };
44 
45 /** \class SkAutoTCallIProc
46 
47 Call a function when this goes out of scope. The template uses two
48 parameters, the object, and a function that is to be called in the destructor.
49 If detach() is called, the object reference is set to null. If the object
50 reference is null when the destructor is called, we do not call the
51 function.
52 */
53 template <typename T, int (*P)(T*)> class SkAutoTCallIProc : SkNoncopyable {
54 public:
SkAutoTCallIProc(T * obj)55     SkAutoTCallIProc(T* obj): fObj(obj) {}
~SkAutoTCallIProc()56     ~SkAutoTCallIProc() { if (fObj) P(fObj); }
detach()57     T* detach() { T* obj = fObj; fObj = NULL; return obj; }
58 private:
59     T* fObj;
60 };
61 
62 // See also SkTScopedPtr.
63 template <typename T> class SkAutoTDelete : SkNoncopyable {
64 public:
fObj(obj)65     SkAutoTDelete(T* obj, bool deleteWhenDone = true) : fObj(obj) {
66         fDeleteWhenDone = deleteWhenDone;
67     }
~SkAutoTDelete()68     ~SkAutoTDelete() { if (fDeleteWhenDone) delete fObj; }
69 
get()70     T*      get() const { return fObj; }
free()71     void    free() { delete fObj; fObj = NULL; }
detach()72     T*      detach() { T* obj = fObj; fObj = NULL; return obj; }
73 
74 private:
75     T*  fObj;
76     bool fDeleteWhenDone;
77 };
78 
79 template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
80 public:
SkAutoTDeleteArray(T array[])81     SkAutoTDeleteArray(T array[]) : fArray(array) {}
~SkAutoTDeleteArray()82     ~SkAutoTDeleteArray() { delete[] fArray; }
83 
get()84     T*      get() const { return fArray; }
free()85     void    free() { delete[] fArray; fArray = NULL; }
detach()86     T*      detach() { T* array = fArray; fArray = NULL; return array; }
87 
88 private:
89     T*  fArray;
90 };
91 
92 /** Allocate an array of T elements, and free the array in the destructor
93  */
94 template <typename T> class SkAutoTArray : SkNoncopyable {
95 public:
96     /** Allocate count number of T elements
97      */
SkAutoTArray(size_t count)98     SkAutoTArray(size_t count) {
99         fArray = NULL;
100         if (count) {
101             fArray = new T[count];
102         }
103         SkDEBUGCODE(fCount = count;)
104     }
105 
~SkAutoTArray()106     ~SkAutoTArray() {
107         delete[] fArray;
108     }
109 
110     /** Return the array of T elements. Will be NULL if count == 0
111      */
get()112     T* get() const { return fArray; }
113 
114     /** Return the nth element in the array
115      */
116     T&  operator[](int index) const {
117         SkASSERT((unsigned)index < fCount);
118         return fArray[index];
119     }
120 
121 private:
122     T*  fArray;
123     SkDEBUGCODE(size_t fCount;)
124 };
125 
126 /** Wraps SkAutoTArray, with room for up to N elements preallocated
127  */
128 template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
129 public:
130     /** Allocate count number of T elements
131      */
SkAutoSTArray(size_t count)132     SkAutoSTArray(size_t count) {
133         if (count > N) {
134             fArray = new T[count];
135         } else if (count) {
136             fArray = new (fStorage) T[count];
137         } else {
138             fArray = NULL;
139         }
140         fCount = count;
141     }
142 
~SkAutoSTArray()143     ~SkAutoSTArray() {
144         if (fCount > N) {
145             delete[] fArray;
146         } else {
147             T* start = fArray;
148             T* iter = start + fCount;
149             while (iter > start) {
150                 (--iter)->~T();
151             }
152         }
153     }
154 
155     /** Return the number of T elements in the array
156      */
count()157     size_t count() const { return fCount; }
158 
159     /** Return the array of T elements. Will be NULL if count == 0
160      */
get()161     T* get() const { return fArray; }
162 
163     /** Return the nth element in the array
164      */
165     T&  operator[](int index) const {
166         SkASSERT((unsigned)index < fCount);
167         return fArray[index];
168     }
169 
170 private:
171     size_t  fCount;
172     T*      fArray;
173     // since we come right after fArray, fStorage should be properly aligned
174     char    fStorage[N * sizeof(T)];
175 };
176 
177 /** Allocate a temp array on the stack/heap.
178     Does NOT call any constructors/destructors on T (i.e. T must be POD)
179 */
180 template <typename T> class SkAutoTMalloc : SkNoncopyable {
181 public:
SkAutoTMalloc(size_t count)182     SkAutoTMalloc(size_t count)
183     {
184         fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
185     }
~SkAutoTMalloc()186     ~SkAutoTMalloc()
187     {
188         sk_free(fPtr);
189     }
get()190     T* get() const { return fPtr; }
191 
192 private:
193     T*  fPtr;
194 };
195 
196 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
197 public:
SkAutoSTMalloc(size_t count)198     SkAutoSTMalloc(size_t count)
199     {
200         if (count <= N)
201             fPtr = fTStorage;
202         else
203             fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
204     }
~SkAutoSTMalloc()205     ~SkAutoSTMalloc()
206     {
207         if (fPtr != fTStorage)
208             sk_free(fPtr);
209     }
get()210     T* get() const { return fPtr; }
211 
212 private:
213     T*          fPtr;
214     union {
215         uint32_t    fStorage32[(N*sizeof(T) + 3) >> 2];
216         T           fTStorage[1];   // do NOT want to invoke T::T()
217     };
218 };
219 
220 #endif
221 
222