| 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 up to N elements preallocated | 167 /** Wraps SkAutoTArray, with room for kCountRequested elements preallocated. |
| 168 */ | 168 */ |
| 169 template <int N, typename T> class SkAutoSTArray : SkNoncopyable { | 169 template <int kCountRequested, 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 > N) { | 198 if (fCount > kCount) { |
| 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 > kCount) { |
| 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 |
| 243 int fCount; | 254 int fCount; |
| 244 T* fArray; | 255 T* fArray; |
| 245 // since we come right after fArray, fStorage should be properly aligned | 256 // since we come right after fArray, fStorage should be properly aligned |
| 246 char fStorage[N * sizeof(T)]; | 257 char fStorage[kCount * sizeof(T)]; |
| 247 }; | 258 }; |
| 248 | 259 |
| 249 /** Manages an array of T elements, freeing the array in the destructor. | 260 /** 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). | 261 * Does NOT call any constructors/destructors on T (T must be POD). |
| 251 */ | 262 */ |
| 252 template <typename T> class SkAutoTMalloc : SkNoncopyable { | 263 template <typename T> class SkAutoTMalloc : SkNoncopyable { |
| 253 public: | 264 public: |
| 254 /** Takes ownership of the ptr. The ptr must be a value which can be passed
to sk_free. */ | 265 /** Takes ownership of the ptr. The ptr must be a value which can be passed
to sk_free. */ |
| 255 explicit SkAutoTMalloc(T* ptr = NULL) { | 266 explicit SkAutoTMalloc(T* ptr = NULL) { |
| 256 fPtr = ptr; | 267 fPtr = ptr; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 T* detach() { | 321 T* detach() { |
| 311 T* ptr = fPtr; | 322 T* ptr = fPtr; |
| 312 fPtr = NULL; | 323 fPtr = NULL; |
| 313 return ptr; | 324 return ptr; |
| 314 } | 325 } |
| 315 | 326 |
| 316 private: | 327 private: |
| 317 T* fPtr; | 328 T* fPtr; |
| 318 }; | 329 }; |
| 319 | 330 |
| 320 template <size_t N, typename T> class SkAutoSTMalloc : SkNoncopyable { | 331 template <size_t kCountRequested, typename T> class SkAutoSTMalloc : SkNoncopyab
le { |
| 321 public: | 332 public: |
| 322 SkAutoSTMalloc() : fPtr(fTStorage) {} | 333 SkAutoSTMalloc() : fPtr(fTStorage) {} |
| 323 | 334 |
| 324 SkAutoSTMalloc(size_t count) { | 335 SkAutoSTMalloc(size_t count) { |
| 325 if (count > N) { | 336 if (count > kCount) { |
| 326 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_M
ALLOC_TEMP); | 337 fPtr = (T*)sk_malloc_flags(count * sizeof(T), SK_MALLOC_THROW | SK_M
ALLOC_TEMP); |
| 327 } else { | 338 } else { |
| 328 fPtr = fTStorage; | 339 fPtr = fTStorage; |
| 329 } | 340 } |
| 330 } | 341 } |
| 331 | 342 |
| 332 ~SkAutoSTMalloc() { | 343 ~SkAutoSTMalloc() { |
| 333 if (fPtr != fTStorage) { | 344 if (fPtr != fTStorage) { |
| 334 sk_free(fPtr); | 345 sk_free(fPtr); |
| 335 } | 346 } |
| 336 } | 347 } |
| 337 | 348 |
| 338 // doesn't preserve contents | 349 // doesn't preserve contents |
| 339 T* reset(size_t count) { | 350 T* reset(size_t count) { |
| 340 if (fPtr != fTStorage) { | 351 if (fPtr != fTStorage) { |
| 341 sk_free(fPtr); | 352 sk_free(fPtr); |
| 342 } | 353 } |
| 343 if (count > N) { | 354 if (count > kCount) { |
| 344 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); | 355 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); |
| 345 } else { | 356 } else { |
| 346 fPtr = fTStorage; | 357 fPtr = fTStorage; |
| 347 } | 358 } |
| 348 return fPtr; | 359 return fPtr; |
| 349 } | 360 } |
| 350 | 361 |
| 351 T* get() const { return fPtr; } | 362 T* get() const { return fPtr; } |
| 352 | 363 |
| 353 operator T*() { | 364 operator T*() { |
| 354 return fPtr; | 365 return fPtr; |
| 355 } | 366 } |
| 356 | 367 |
| 357 operator const T*() const { | 368 operator const T*() const { |
| 358 return fPtr; | 369 return fPtr; |
| 359 } | 370 } |
| 360 | 371 |
| 361 T& operator[](int index) { | 372 T& operator[](int index) { |
| 362 return fPtr[index]; | 373 return fPtr[index]; |
| 363 } | 374 } |
| 364 | 375 |
| 365 const T& operator[](int index) const { | 376 const T& operator[](int index) const { |
| 366 return fPtr[index]; | 377 return fPtr[index]; |
| 367 } | 378 } |
| 368 | 379 |
| 369 // Reallocs the array, can be used to shrink the allocation. Makes no attem
pt to be intelligent | 380 // Reallocs the array, can be used to shrink the allocation. Makes no attem
pt to be intelligent |
| 370 void realloc(size_t count) { | 381 void realloc(size_t count) { |
| 371 if (count > N) { | 382 if (count > kCount) { |
| 372 if (fPtr == fTStorage) { | 383 if (fPtr == fTStorage) { |
| 373 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); | 384 fPtr = (T*)sk_malloc_throw(count * sizeof(T)); |
| 374 memcpy(fPtr, fTStorage, N * sizeof(T)); | 385 memcpy(fPtr, fTStorage, kCount * sizeof(T)); |
| 375 } else { | 386 } else { |
| 376 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); | 387 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); |
| 377 } | 388 } |
| 378 } else if (fPtr != fTStorage) { | 389 } else if (fPtr != fTStorage) { |
| 379 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); | 390 fPtr = (T*)sk_realloc_throw(fPtr, count * sizeof(T)); |
| 380 } | 391 } |
| 381 } | 392 } |
| 382 | 393 |
| 383 private: | 394 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 |
| 384 T* fPtr; | 408 T* fPtr; |
| 385 union { | 409 union { |
| 386 uint32_t fStorage32[(N*sizeof(T) + 3) >> 2]; | 410 uint32_t fStorage32[SkAlign4(kCount*sizeof(T)) >> 2]; |
| 387 T fTStorage[1]; // do NOT want to invoke T::T() | 411 T fTStorage[1]; // do NOT want to invoke T::T() |
| 388 }; | 412 }; |
| 389 }; | 413 }; |
| 390 | 414 |
| 391 ////////////////////////////////////////////////////////////////////////////////
////////////////// | 415 ////////////////////////////////////////////////////////////////////////////////
////////////////// |
| 392 | 416 |
| 393 /** | 417 /** |
| 394 * Pass the object and the storage that was offered during SkInPlaceNewCheck, a
nd this will | 418 * 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. | 419 * safely destroy (and free if it was dynamically allocated) the object. |
| 396 */ | 420 */ |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 449 * Returns void* because this object does not initialize the | 473 * Returns void* because this object does not initialize the |
| 450 * memory. Use placement new for types that require a cons. | 474 * memory. Use placement new for types that require a cons. |
| 451 */ | 475 */ |
| 452 void* get() { return fStorage.get(); } | 476 void* get() { return fStorage.get(); } |
| 453 const void* get() const { return fStorage.get(); } | 477 const void* get() const { return fStorage.get(); } |
| 454 private: | 478 private: |
| 455 SkAlignedSStorage<sizeof(T)*N> fStorage; | 479 SkAlignedSStorage<sizeof(T)*N> fStorage; |
| 456 }; | 480 }; |
| 457 | 481 |
| 458 #endif | 482 #endif |
| OLD | NEW |