OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2006 The Android Open Source Project | 3 * Copyright 2006 The Android Open Source Project |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 | 9 |
10 #ifndef SkTemplates_DEFINED | 10 #ifndef SkTemplates_DEFINED |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
157 void swap(SkAutoTArray& other) { | 157 void swap(SkAutoTArray& other) { |
158 SkTSwap(fArray, other.fArray); | 158 SkTSwap(fArray, other.fArray); |
159 SkDEBUGCODE(SkTSwap(fCount, other.fCount)); | 159 SkDEBUGCODE(SkTSwap(fCount, other.fCount)); |
160 } | 160 } |
161 | 161 |
162 private: | 162 private: |
163 T* fArray; | 163 T* fArray; |
164 SkDEBUGCODE(int fCount;) | 164 SkDEBUGCODE(int fCount;) |
165 }; | 165 }; |
166 | 166 |
167 /** Wraps SkAutoTArray, with room for kCountRequested elements preallocated. | 167 /** Wraps SkAutoTArray, with room for up to N elements preallocated |
168 */ | 168 */ |
169 template <int kCountRequested, typename T> class SkAutoSTArray : SkNoncopyable { | 169 template <int N, typename T> class SkAutoSTArray : SkNoncopyable { |
170 public: | 170 public: |
171 /** Initialize with no objects */ | 171 /** Initialize with no objects */ |
172 SkAutoSTArray() { | 172 SkAutoSTArray() { |
173 fArray = NULL; | 173 fArray = NULL; |
174 fCount = 0; | 174 fCount = 0; |
175 } | 175 } |
176 | 176 |
177 /** Allocate count number of T elements | 177 /** Allocate count number of T elements |
178 */ | 178 */ |
179 SkAutoSTArray(int count) { | 179 SkAutoSTArray(int count) { |
180 fArray = NULL; | 180 fArray = NULL; |
181 fCount = 0; | 181 fCount = 0; |
182 this->reset(count); | 182 this->reset(count); |
183 } | 183 } |
184 | 184 |
185 ~SkAutoSTArray() { | 185 ~SkAutoSTArray() { |
186 this->reset(0); | 186 this->reset(0); |
187 } | 187 } |
188 | 188 |
189 /** Destroys previous objects in the array and default constructs count numb
er of objects */ | 189 /** Destroys previous objects in the array and default constructs count numb
er of objects */ |
190 void reset(int count) { | 190 void reset(int count) { |
191 T* start = fArray; | 191 T* start = fArray; |
192 T* iter = start + fCount; | 192 T* iter = start + fCount; |
193 while (iter > start) { | 193 while (iter > start) { |
194 (--iter)->~T(); | 194 (--iter)->~T(); |
195 } | 195 } |
196 | 196 |
197 if (fCount != count) { | 197 if (fCount != count) { |
198 if (fCount > kCount) { | 198 if (fCount > N) { |
199 // 'fArray' was allocated last time so free it now | 199 // 'fArray' was allocated last time so free it now |
200 SkASSERT((T*) fStorage != fArray); | 200 SkASSERT((T*) fStorage != fArray); |
201 sk_free(fArray); | 201 sk_free(fArray); |
202 } | 202 } |
203 | 203 |
204 if (count > kCount) { | 204 if (count > N) { |
205 const uint64_t size64 = sk_64_mul(count, sizeof(T)); | 205 const uint64_t size64 = sk_64_mul(count, sizeof(T)); |
206 const size_t size = static_cast<size_t>(size64); | 206 const size_t size = static_cast<size_t>(size64); |
207 if (size != size64) { | 207 if (size != size64) { |
208 sk_out_of_memory(); | 208 sk_out_of_memory(); |
209 } | 209 } |
210 fArray = (T*) sk_malloc_throw(size); | 210 fArray = (T*) sk_malloc_throw(size); |
211 } else if (count > 0) { | 211 } else if (count > 0) { |
212 fArray = (T*) fStorage; | 212 fArray = (T*) fStorage; |
213 } else { | 213 } else { |
214 fArray = NULL; | 214 fArray = NULL; |
(...skipping 18 matching lines...) Expand all Loading... |
233 T* get() const { return fArray; } | 233 T* get() const { return fArray; } |
234 | 234 |
235 /** Return the nth element in the array | 235 /** Return the nth element in the array |
236 */ | 236 */ |
237 T& operator[](int index) const { | 237 T& operator[](int index) const { |
238 SkASSERT(index < fCount); | 238 SkASSERT(index < fCount); |
239 return fArray[index]; | 239 return fArray[index]; |
240 } | 240 } |
241 | 241 |
242 private: | 242 private: |
243 #if defined(GOOGLE3) | |
244 // Stack frame size is limited for GOOGLE3. 4k is less than the actual max,
but some functions | |
245 // have multiple large stack allocations. | |
246 static const int kMaxBytes = 4 * 1024; | |
247 static const int kCount = kCountRequested * sizeof(T) > kMaxBytes | |
248 ? kMaxBytes / sizeof(T) | |
249 : kCountRequested; | |
250 #else | |
251 static const int kCount = kCountRequested; | |
252 #endif | |
253 | |
254 int fCount; | 243 int fCount; |
255 T* fArray; | 244 T* fArray; |
256 // since we come right after fArray, fStorage should be properly aligned | 245 // since we come right after fArray, fStorage should be properly aligned |
257 char fStorage[kCount * sizeof(T)]; | 246 char fStorage[N * sizeof(T)]; |
258 }; | 247 }; |
259 | 248 |
260 /** Manages an array of T elements, freeing the array in the destructor. | 249 /** Manages an array of T elements, freeing the array in the destructor. |
261 * Does NOT call any constructors/destructors on T (T must be POD). | 250 * Does NOT call any constructors/destructors on T (T must be POD). |
262 */ | 251 */ |
263 template <typename T> class SkAutoTMalloc : SkNoncopyable { | 252 template <typename T> class SkAutoTMalloc : SkNoncopyable { |
264 public: | 253 public: |
265 /** Takes ownership of the ptr. The ptr must be a value which can be passed
to sk_free. */ | 254 /** Takes ownership of the ptr. The ptr must be a value which can be passed
to sk_free. */ |
266 explicit SkAutoTMalloc(T* ptr = NULL) { | 255 explicit SkAutoTMalloc(T* ptr = NULL) { |
267 fPtr = ptr; | 256 fPtr = ptr; |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
321 T* detach() { | 310 T* detach() { |
322 T* ptr = fPtr; | 311 T* ptr = fPtr; |
323 fPtr = NULL; | 312 fPtr = NULL; |
324 return ptr; | 313 return ptr; |
325 } | 314 } |
326 | 315 |
327 private: | 316 private: |
328 T* fPtr; | 317 T* fPtr; |
329 }; | 318 }; |
330 | 319 |
331 template <size_t kCountRequested, typename T> class SkAutoSTMalloc : SkNoncopyab
le { | 320 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable { |
332 public: | 321 public: |
333 SkAutoSTMalloc() : fPtr(fTStorage) {} | 322 SkAutoSTMalloc() : fPtr(fTStorage) {} |
334 | 323 |
335 SkAutoSTMalloc(size_t count) { | 324 SkAutoSTMalloc(size_t count) { |
336 if (count > kCount) { | 325 if (count > N) { |
337 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_M
ALLOC_TEMP); | 326 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_M
ALLOC_TEMP); |
338 } else { | 327 } else { |
339 fPtr = fTStorage; | 328 fPtr = fTStorage; |
340 } | 329 } |
341 } | 330 } |
342 | 331 |
343 ~SkAutoSTMalloc() { | 332 ~SkAutoSTMalloc() { |
344 if (fPtr != fTStorage) { | 333 if (fPtr != fTStorage) { |
345 sk_free(fPtr); | 334 sk_free(fPtr); |
346 } | 335 } |
347 } | 336 } |
348 | 337 |
349 // doesn't preserve contents | 338 // doesn't preserve contents |
350 T* reset(size_t count) { | 339 T* reset(size_t count) { |
351 if (fPtr != fTStorage) { | 340 if (fPtr != fTStorage) { |
352 sk_free(fPtr); | 341 sk_free(fPtr); |
353 } | 342 } |
354 if (count > kCount) { | 343 if (count > N) { |
355 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); | 344 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); |
356 } else { | 345 } else { |
357 fPtr = fTStorage; | 346 fPtr = fTStorage; |
358 } | 347 } |
359 return fPtr; | 348 return fPtr; |
360 } | 349 } |
361 | 350 |
362 T* get() const { return fPtr; } | 351 T* get() const { return fPtr; } |
363 | 352 |
364 operator T*() { | 353 operator T*() { |
365 return fPtr; | 354 return fPtr; |
366 } | 355 } |
367 | 356 |
368 operator const T*() const { | 357 operator const T*() const { |
369 return fPtr; | 358 return fPtr; |
370 } | 359 } |
371 | 360 |
372 T& operator[](int index) { | 361 T& operator[](int index) { |
373 return fPtr[index]; | 362 return fPtr[index]; |
374 } | 363 } |
375 | 364 |
376 const T& operator[](int index) const { | 365 const T& operator[](int index) const { |
377 return fPtr[index]; | 366 return fPtr[index]; |
378 } | 367 } |
379 | 368 |
380 // Reallocs the array, can be used to shrink the allocation. Makes no attem
pt to be intelligent | 369 // Reallocs the array, can be used to shrink the allocation. Makes no attem
pt to be intelligent |
381 void realloc(size_t count) { | 370 void realloc(size_t count) { |
382 if (count > kCount) { | 371 if (count > N) { |
383 if (fPtr == fTStorage) { | 372 if (fPtr == fTStorage) { |
384 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); | 373 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); |
385 memcpy(fPtr, fTStorage, kCount * sizeof(T)); | 374 memcpy(fPtr, fTStorage, N * sizeof(T)); |
386 } else { | 375 } else { |
387 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); | 376 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); |
388 } | 377 } |
389 } else if (fPtr != fTStorage) { | 378 } else if (fPtr != fTStorage) { |
390 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); | 379 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); |
391 } | 380 } |
392 } | 381 } |
393 | 382 |
394 private: | 383 private: |
395 // Since we use uint32_t storage, we might be able to get more elements for
free. | |
396 static const size_t kCountWithPadding = SkAlign4(kCountRequested*sizeof(T))
/ sizeof(T); | |
397 #if defined(GOOGLE3) | |
398 // Stack frame size is limited for GOOGLE3. 4k is less than the actual max,
but some functions | |
399 // have multiple large stack allocations. | |
400 static const size_t kMaxBytes = 4 * 1024; | |
401 static const size_t kCount = kCountRequested * sizeof(T) > kMaxBytes | |
402 ? kMaxBytes / sizeof(T) | |
403 : kCountWithPadding; | |
404 #else | |
405 static const size_t kCount = kCountWithPadding; | |
406 #endif | |
407 | |
408 T* fPtr; | 384 T* fPtr; |
409 union { | 385 union { |
410 uint32_t fStorage32[SkAlign4(kCount*sizeof(T)) >> 2]; | 386 uint32_t fStorage32[(N*sizeof(T) + 3) >> 2]; |
411 T fTStorage[1]; // do NOT want to invoke T::T() | 387 T fTStorage[1]; // do NOT want to invoke T::T() |
412 }; | 388 }; |
413 }; | 389 }; |
414 | 390 |
415 ////////////////////////////////////////////////////////////////////////////////
////////////////// | 391 ////////////////////////////////////////////////////////////////////////////////
////////////////// |
416 | 392 |
417 /** | 393 /** |
418 * Pass the object and the storage that was offered during SkInPlaceNewCheck, a
nd this will | 394 * Pass the object and the storage that was offered during SkInPlaceNewCheck, a
nd this will |
419 * safely destroy (and free if it was dynamically allocated) the object. | 395 * safely destroy (and free if it was dynamically allocated) the object. |
420 */ | 396 */ |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
473 * Returns void* because this object does not initialize the | 449 * Returns void* because this object does not initialize the |
474 * memory. Use placement new for types that require a cons. | 450 * memory. Use placement new for types that require a cons. |
475 */ | 451 */ |
476 void* get() { return fStorage.get(); } | 452 void* get() { return fStorage.get(); } |
477 const void* get() const { return fStorage.get(); } | 453 const void* get() const { return fStorage.get(); } |
478 private: | 454 private: |
479 SkAlignedSStorage<sizeof(T)*N> fStorage; | 455 SkAlignedSStorage<sizeof(T)*N> fStorage; |
480 }; | 456 }; |
481 | 457 |
482 #endif | 458 #endif |
OLD | NEW |