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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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 > N) { | 198 if (fCount > N_ADJ) { |
mtklein
2016/02/02 03:04:29
Ditto here. It just seems easy to accidentally us
dogben
2016/02/02 19:39:34
Done. I made the naming consistent with SkAutoSMal
| |
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 > N) { | 204 if (count > N_ADJ) { |
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 MAX_BYTES = 4 * 1024; | |
247 static const int N_ADJ = N * sizeof(T) > MAX_BYTES ? MAX_BYTES / sizeof(T) : N; | |
248 #else | |
249 static const int N_ADJ = N; | |
250 #endif | |
251 | |
243 int fCount; | 252 int fCount; |
244 T* fArray; | 253 T* fArray; |
245 // since we come right after fArray, fStorage should be properly aligned | 254 // since we come right after fArray, fStorage should be properly aligned |
246 char fStorage[N * sizeof(T)]; | 255 char fStorage[N_ADJ * sizeof(T)]; |
247 }; | 256 }; |
248 | 257 |
249 /** Manages an array of T elements, freeing the array in the destructor. | 258 /** Manages an array of T elements, freeing the array in the destructor. |
250 * Does NOT call any constructors/destructors on T (T must be POD). | 259 * Does NOT call any constructors/destructors on T (T must be POD). |
251 */ | 260 */ |
252 template <typename T> class SkAutoTMalloc : SkNoncopyable { | 261 template <typename T> class SkAutoTMalloc : SkNoncopyable { |
253 public: | 262 public: |
254 /** Takes ownership of the ptr. The ptr must be a value which can be passed to sk_free. */ | 263 /** Takes ownership of the ptr. The ptr must be a value which can be passed to sk_free. */ |
255 explicit SkAutoTMalloc(T* ptr = NULL) { | 264 explicit SkAutoTMalloc(T* ptr = NULL) { |
256 fPtr = ptr; | 265 fPtr = ptr; |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
315 | 324 |
316 private: | 325 private: |
317 T* fPtr; | 326 T* fPtr; |
318 }; | 327 }; |
319 | 328 |
320 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable { | 329 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable { |
321 public: | 330 public: |
322 SkAutoSTMalloc() : fPtr(fTStorage) {} | 331 SkAutoSTMalloc() : fPtr(fTStorage) {} |
323 | 332 |
324 SkAutoSTMalloc(size_t count) { | 333 SkAutoSTMalloc(size_t count) { |
325 if (count > N) { | 334 if (count > N_ADJ) { |
326 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_M ALLOC_TEMP); | 335 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_M ALLOC_TEMP); |
327 } else { | 336 } else { |
328 fPtr = fTStorage; | 337 fPtr = fTStorage; |
329 } | 338 } |
330 } | 339 } |
331 | 340 |
332 ~SkAutoSTMalloc() { | 341 ~SkAutoSTMalloc() { |
333 if (fPtr != fTStorage) { | 342 if (fPtr != fTStorage) { |
334 sk_free(fPtr); | 343 sk_free(fPtr); |
335 } | 344 } |
336 } | 345 } |
337 | 346 |
338 // doesn't preserve contents | 347 // doesn't preserve contents |
339 T* reset(size_t count) { | 348 T* reset(size_t count) { |
340 if (fPtr != fTStorage) { | 349 if (fPtr != fTStorage) { |
341 sk_free(fPtr); | 350 sk_free(fPtr); |
342 } | 351 } |
343 if (count > N) { | 352 if (count > N_ADJ) { |
344 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); | 353 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); |
345 } else { | 354 } else { |
346 fPtr = fTStorage; | 355 fPtr = fTStorage; |
347 } | 356 } |
348 return fPtr; | 357 return fPtr; |
349 } | 358 } |
350 | 359 |
351 T* get() const { return fPtr; } | 360 T* get() const { return fPtr; } |
352 | 361 |
353 operator T*() { | 362 operator T*() { |
354 return fPtr; | 363 return fPtr; |
355 } | 364 } |
356 | 365 |
357 operator const T*() const { | 366 operator const T*() const { |
358 return fPtr; | 367 return fPtr; |
359 } | 368 } |
360 | 369 |
361 T& operator[](int index) { | 370 T& operator[](int index) { |
362 return fPtr[index]; | 371 return fPtr[index]; |
363 } | 372 } |
364 | 373 |
365 const T& operator[](int index) const { | 374 const T& operator[](int index) const { |
366 return fPtr[index]; | 375 return fPtr[index]; |
367 } | 376 } |
368 | 377 |
369 // Reallocs the array, can be used to shrink the allocation. Makes no attem pt to be intelligent | 378 // Reallocs the array, can be used to shrink the allocation. Makes no attem pt to be intelligent |
370 void realloc(size_t count) { | 379 void realloc(size_t count) { |
371 if (count > N) { | 380 if (count > N_ADJ) { |
372 if (fPtr == fTStorage) { | 381 if (fPtr == fTStorage) { |
373 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); | 382 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); |
374 memcpy(fPtr, fTStorage, N * sizeof(T)); | 383 memcpy(fPtr, fTStorage, N_ADJ * sizeof(T)); |
375 } else { | 384 } else { |
376 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); | 385 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); |
377 } | 386 } |
378 } else if (fPtr != fTStorage) { | 387 } else if (fPtr != fTStorage) { |
379 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); | 388 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); |
380 } | 389 } |
381 } | 390 } |
382 | 391 |
383 private: | 392 private: |
393 // Since we use uint32_t storage, we might be able to get more elements for free. | |
394 static const size_t N_WITH_PADDING = (((N*sizeof(T) + 3) >> 2) << 2) / sizeo f(T); | |
395 #if defined(GOOGLE3) | |
396 // Stack frame size is limited for GOOGLE3. 4k is less than the actual max, but some functions | |
397 // have multiple large stack allocations. | |
398 static const size_t MAX_BYTES = 4 * 1024; | |
399 static const size_t N_ADJ = N * sizeof(T) > MAX_BYTES ? MAX_BYTES / sizeof(T ) : N_WITH_PADDING; | |
400 #else | |
401 static const size_t N_ADJ = N_WITH_PADDING; | |
402 #endif | |
403 | |
384 T* fPtr; | 404 T* fPtr; |
385 union { | 405 union { |
386 uint32_t fStorage32[(N*sizeof(T) + 3) >> 2]; | 406 uint32_t fStorage32[(N_ADJ*sizeof(T) + 3) >> 2]; |
387 T fTStorage[1]; // do NOT want to invoke T::T() | 407 T fTStorage[1]; // do NOT want to invoke T::T() |
388 }; | 408 }; |
389 }; | 409 }; |
390 | 410 |
391 //////////////////////////////////////////////////////////////////////////////// ////////////////// | 411 //////////////////////////////////////////////////////////////////////////////// ////////////////// |
392 | 412 |
393 /** | 413 /** |
394 * Pass the object and the storage that was offered during SkInPlaceNewCheck, a nd this will | 414 * Pass the object and the storage that was offered during SkInPlaceNewCheck, a nd this will |
395 * safely destroy (and free if it was dynamically allocated) the object. | 415 * safely destroy (and free if it was dynamically allocated) the object. |
396 */ | 416 */ |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
449 * Returns void* because this object does not initialize the | 469 * Returns void* because this object does not initialize the |
450 * memory. Use placement new for types that require a cons. | 470 * memory. Use placement new for types that require a cons. |
451 */ | 471 */ |
452 void* get() { return fStorage.get(); } | 472 void* get() { return fStorage.get(); } |
453 const void* get() const { return fStorage.get(); } | 473 const void* get() const { return fStorage.get(); } |
454 private: | 474 private: |
455 SkAlignedSStorage<sizeof(T)*N> fStorage; | 475 SkAlignedSStorage<sizeof(T)*N> fStorage; |
456 }; | 476 }; |
457 | 477 |
458 #endif | 478 #endif |
OLD | NEW |