OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2006 The Android Open Source Project | 2 * Copyright 2006 The Android Open Source Project |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #ifndef SkTypes_DEFINED | 8 #ifndef SkTypes_DEFINED |
9 #define SkTypes_DEFINED | 9 #define SkTypes_DEFINED |
10 | 10 |
(...skipping 588 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 return ptr; | 599 return ptr; |
600 } | 600 } |
601 | 601 |
602 private: | 602 private: |
603 void* fPtr; | 603 void* fPtr; |
604 size_t fSize; // can be larger than the requested size (see kReuse) | 604 size_t fSize; // can be larger than the requested size (see kReuse) |
605 }; | 605 }; |
606 #define SkAutoMalloc(...) SK_REQUIRE_LOCAL_VAR(SkAutoMalloc) | 606 #define SkAutoMalloc(...) SK_REQUIRE_LOCAL_VAR(SkAutoMalloc) |
607 | 607 |
608 /** | 608 /** |
609 * Manage an allocated block of memory. If the requested size is <= kSize, then | 609 * Manage an allocated block of memory. If the requested size is <= kSizeReques
ted (or slightly |
610 * the allocation will come from the stack rather than the heap. This object | 610 * more), then the allocation will come from the stack rather than the heap. Th
is object is the |
611 * is the sole manager of the lifetime of the block, so the caller must not | 611 * sole manager of the lifetime of the block, so the caller must not call sk_fr
ee() or delete on |
612 * call sk_free() or delete on the block. | 612 * the block. |
613 */ | 613 */ |
614 template <size_t kSize> class SkAutoSMalloc : SkNoncopyable { | 614 template <size_t kSizeRequested> class SkAutoSMalloc : SkNoncopyable { |
615 public: | 615 public: |
616 /** | 616 /** |
617 * Creates initially empty storage. get() returns a ptr, but it is to | 617 * Creates initially empty storage. get() returns a ptr, but it is to a zer
o-byte allocation. |
618 * a zero-byte allocation. Must call reset(size) to return an allocated | 618 * Must call reset(size) to return an allocated block. |
619 * block. | |
620 */ | 619 */ |
621 SkAutoSMalloc() { | 620 SkAutoSMalloc() { |
622 fPtr = fStorage; | 621 fPtr = fStorage; |
623 fSize = kSize; | 622 fSize = kSize; |
624 } | 623 } |
625 | 624 |
626 /** | 625 /** |
627 * Allocate a block of the specified size. If size <= kSize, then the | 626 * Allocate a block of the specified size. If size <= kSizeRequested (or sl
ightly more), then |
628 * allocation will come from the stack, otherwise it will be dynamically | 627 * the allocation will come from the stack, otherwise it will be dynamicall
y allocated. |
629 * allocated. | |
630 */ | 628 */ |
631 explicit SkAutoSMalloc(size_t size) { | 629 explicit SkAutoSMalloc(size_t size) { |
632 fPtr = fStorage; | 630 fPtr = fStorage; |
633 fSize = kSize; | 631 fSize = kSize; |
634 this->reset(size); | 632 this->reset(size); |
635 } | 633 } |
636 | 634 |
637 /** | 635 /** |
638 * Free the allocated block (if any). If the block was small enought to | 636 * Free the allocated block (if any). If the block was small enough to have
been allocated on |
639 * have been allocated on the stack (size <= kSize) then this does nothing. | 637 * the stack, then this does nothing. |
640 */ | 638 */ |
641 ~SkAutoSMalloc() { | 639 ~SkAutoSMalloc() { |
642 if (fPtr != (void*)fStorage) { | 640 if (fPtr != (void*)fStorage) { |
643 sk_free(fPtr); | 641 sk_free(fPtr); |
644 } | 642 } |
645 } | 643 } |
646 | 644 |
647 /** | 645 /** |
648 * Return the allocated block. May return non-null even if the block is | 646 * Return the allocated block. May return non-null even if the block is of
zero size. Since |
649 * of zero size. Since this may be on the stack or dynamically allocated, | 647 * this may be on the stack or dynamically allocated, the caller must not c
all sk_free() on it, |
650 * the caller must not call sk_free() on it, but must rely on SkAutoSMalloc | 648 * but must rely on SkAutoSMalloc to manage it. |
651 * to manage it. | |
652 */ | 649 */ |
653 void* get() const { return fPtr; } | 650 void* get() const { return fPtr; } |
654 | 651 |
655 /** | 652 /** |
656 * Return a new block of the requested size, freeing (as necessary) any | 653 * Return a new block of the requested size, freeing (as necessary) any pre
viously allocated |
657 * previously allocated block. As with the constructor, if size <= kSize | 654 * block. As with the constructor, if size <= kSizeRequested (or slightly m
ore) then the return |
658 * then the return block may be allocated locally, rather than from the | 655 * block may be allocated locally, rather than from the heap. |
659 * heap. | |
660 */ | 656 */ |
661 void* reset(size_t size, | 657 void* reset(size_t size, |
662 SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink, | 658 SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink, |
663 bool* didChangeAlloc = NULL) { | 659 bool* didChangeAlloc = NULL) { |
664 size = (size < kSize) ? kSize : size; | 660 size = (size < kSize) ? kSize : size; |
665 bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink |
| size > fSize); | 661 bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink |
| size > fSize); |
666 if (didChangeAlloc) { | 662 if (didChangeAlloc) { |
667 *didChangeAlloc = alloc; | 663 *didChangeAlloc = alloc; |
668 } | 664 } |
669 if (alloc) { | 665 if (alloc) { |
670 if (fPtr != (void*)fStorage) { | 666 if (fPtr != (void*)fStorage) { |
671 sk_free(fPtr); | 667 sk_free(fPtr); |
672 } | 668 } |
673 | 669 |
674 if (size == kSize) { | 670 if (size == kSize) { |
675 SkASSERT(fPtr != fStorage); // otherwise we lied when setting di
dChangeAlloc. | 671 SkASSERT(fPtr != fStorage); // otherwise we lied when setting di
dChangeAlloc. |
676 fPtr = fStorage; | 672 fPtr = fStorage; |
677 } else { | 673 } else { |
678 fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); | 674 fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); |
679 } | 675 } |
680 | 676 |
681 fSize = size; | 677 fSize = size; |
682 } | 678 } |
683 SkASSERT(fSize >= size && fSize >= kSize); | 679 SkASSERT(fSize >= size && fSize >= kSize); |
684 SkASSERT((fPtr == fStorage) || fSize > kSize); | 680 SkASSERT((fPtr == fStorage) || fSize > kSize); |
685 return fPtr; | 681 return fPtr; |
686 } | 682 } |
687 | 683 |
688 private: | 684 private: |
| 685 // Align up to 32 bits. |
| 686 static const size_t kSizeAlign4 = SkAlign4(kSizeRequested); |
| 687 #if defined(GOOGLE3) |
| 688 // Stack frame size is limited for GOOGLE3. 4k is less than the actual max,
but some functions |
| 689 // have multiple large stack allocations. |
| 690 static const size_t kMaxBytes = 4 * 1024; |
| 691 static const size_t kSize = kSizeRequested > kMaxBytes ? kMaxBytes : kSizeAl
ign4; |
| 692 #else |
| 693 static const size_t kSize = kSizeAlign4; |
| 694 #endif |
| 695 |
689 void* fPtr; | 696 void* fPtr; |
690 size_t fSize; // can be larger than the requested size (see kReuse) | 697 size_t fSize; // can be larger than the requested size (see kReuse) |
691 uint32_t fStorage[(kSize + 3) >> 2]; | 698 uint32_t fStorage[kSize >> 2]; |
692 }; | 699 }; |
693 // Can't guard the constructor because it's a template class. | 700 // Can't guard the constructor because it's a template class. |
694 | 701 |
695 #endif /* C++ */ | 702 #endif /* C++ */ |
696 | 703 |
697 #endif | 704 #endif |
OLD | NEW |