• 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 template <typename T> class SkAutoTDelete : SkNoncopyable {
63 public:
SkAutoTDelete(T * obj)64     SkAutoTDelete(T* obj) : fObj(obj) {}
~SkAutoTDelete()65     ~SkAutoTDelete() { delete fObj; }
66 
get()67     T*      get() const { return fObj; }
free()68     void    free() { delete fObj; fObj = NULL; }
detach()69     T*      detach() { T* obj = fObj; fObj = NULL; return obj; }
70 
71 private:
72     T*  fObj;
73 };
74 
75 template <typename T> class SkAutoTDeleteArray : SkNoncopyable {
76 public:
SkAutoTDeleteArray(T array[])77     SkAutoTDeleteArray(T array[]) : fArray(array) {}
~SkAutoTDeleteArray()78     ~SkAutoTDeleteArray() { delete[] fArray; }
79 
get()80     T*      get() const { return fArray; }
free()81     void    free() { delete[] fArray; fArray = NULL; }
detach()82     T*      detach() { T* array = fArray; fArray = NULL; return array; }
83 
84 private:
85     T*  fArray;
86 };
87 
88 /** Allocate an array of T elements, and free the array in the destructor
89  */
90 template <typename T> class SkAutoTArray : SkNoncopyable {
91 public:
92     /** Allocate count number of T elements
93      */
SkAutoTArray(size_t count)94     SkAutoTArray(size_t count) {
95         fArray = NULL;
96         if (count) {
97             fArray = new T[count];
98         }
99         SkDEBUGCODE(fCount = count;)
100     }
101 
~SkAutoTArray()102     ~SkAutoTArray() {
103         delete[] fArray;
104     }
105 
106     /** Return the array of T elements. Will be NULL if count == 0
107      */
get()108     T* get() const { return fArray; }
109 
110     /** Return the nth element in the array
111      */
112     T&  operator[](int index) const {
113         SkASSERT((unsigned)index < fCount);
114         return fArray[index];
115     }
116 
117 private:
118     T*  fArray;
119     SkDEBUGCODE(size_t fCount;)
120 };
121 
122 /** Wraps SkAutoTArray, with room for up to N elements preallocated
123  */
124 template <size_t N, typename T> class SkAutoSTArray : SkNoncopyable {
125 public:
126     /** Allocate count number of T elements
127      */
SkAutoSTArray(size_t count)128     SkAutoSTArray(size_t count) {
129         if (count > N) {
130             fArray = new T[count];
131         } else if (count) {
132             fArray = new (fStorage) T[count];
133         } else {
134             fArray = NULL;
135         }
136         fCount = count;
137     }
138 
~SkAutoSTArray()139     ~SkAutoSTArray() {
140         if (fCount > N) {
141             delete[] fArray;
142         } else {
143             T* start = fArray;
144             T* iter = start + fCount;
145             while (iter > start) {
146                 (--iter)->~T();
147             }
148         }
149     }
150 
151     /** Return the number of T elements in the array
152      */
count()153     size_t count() const { return fCount; }
154 
155     /** Return the array of T elements. Will be NULL if count == 0
156      */
get()157     T* get() const { return fArray; }
158 
159     /** Return the nth element in the array
160      */
161     T&  operator[](int index) const {
162         SkASSERT((unsigned)index < fCount);
163         return fArray[index];
164     }
165 
166 private:
167     size_t  fCount;
168     T*      fArray;
169     // since we come right after fArray, fStorage should be properly aligned
170     char    fStorage[N * sizeof(T)];
171 };
172 
173 /** Allocate a temp array on the stack/heap.
174     Does NOT call any constructors/destructors on T (i.e. T must be POD)
175 */
176 template <typename T> class SkAutoTMalloc : SkNoncopyable {
177 public:
SkAutoTMalloc(size_t count)178     SkAutoTMalloc(size_t count)
179     {
180         fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
181     }
~SkAutoTMalloc()182     ~SkAutoTMalloc()
183     {
184         sk_free(fPtr);
185     }
get()186     T* get() const { return fPtr; }
187 
188 private:
189     T*  fPtr;
190 };
191 
192 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable {
193 public:
SkAutoSTMalloc(size_t count)194     SkAutoSTMalloc(size_t count)
195     {
196         if (count <= N)
197             fPtr = fTStorage;
198         else
199             fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_MALLOC_TEMP);
200     }
~SkAutoSTMalloc()201     ~SkAutoSTMalloc()
202     {
203         if (fPtr != fTStorage)
204             sk_free(fPtr);
205     }
get()206     T* get() const { return fPtr; }
207 
208 private:
209     T*          fPtr;
210     union {
211         uint32_t    fStorage32[(N*sizeof(T) + 3) >> 2];
212         T           fTStorage[1];   // do NOT want to invoke T::T()
213     };
214 };
215 
216 #endif
217 
218