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 <= kSizeReques
ted (or slightly | 609 * Manage an allocated block of memory. If the requested size is <= kSize, then |
610 * more), then the allocation will come from the stack rather than the heap. Th
is object is the | 610 * the allocation will come from the stack rather than the heap. This object |
611 * sole manager of the lifetime of the block, so the caller must not call sk_fr
ee() or delete on | 611 * is the sole manager of the lifetime of the block, so the caller must not |
612 * the block. | 612 * call sk_free() or delete on the block. |
613 */ | 613 */ |
614 template <size_t kSizeRequested> class SkAutoSMalloc : SkNoncopyable { | 614 template <size_t kSize> class SkAutoSMalloc : SkNoncopyable { |
615 public: | 615 public: |
616 /** | 616 /** |
617 * Creates initially empty storage. get() returns a ptr, but it is to a zer
o-byte allocation. | 617 * Creates initially empty storage. get() returns a ptr, but it is to |
618 * Must call reset(size) to return an allocated block. | 618 * a zero-byte allocation. Must call reset(size) to return an allocated |
| 619 * block. |
619 */ | 620 */ |
620 SkAutoSMalloc() { | 621 SkAutoSMalloc() { |
621 fPtr = fStorage; | 622 fPtr = fStorage; |
622 fSize = kSize; | 623 fSize = kSize; |
623 } | 624 } |
624 | 625 |
625 /** | 626 /** |
626 * Allocate a block of the specified size. If size <= kSizeRequested (or sl
ightly more), then | 627 * Allocate a block of the specified size. If size <= kSize, then the |
627 * the allocation will come from the stack, otherwise it will be dynamicall
y allocated. | 628 * allocation will come from the stack, otherwise it will be dynamically |
| 629 * allocated. |
628 */ | 630 */ |
629 explicit SkAutoSMalloc(size_t size) { | 631 explicit SkAutoSMalloc(size_t size) { |
630 fPtr = fStorage; | 632 fPtr = fStorage; |
631 fSize = kSize; | 633 fSize = kSize; |
632 this->reset(size); | 634 this->reset(size); |
633 } | 635 } |
634 | 636 |
635 /** | 637 /** |
636 * Free the allocated block (if any). If the block was small enough to have
been allocated on | 638 * Free the allocated block (if any). If the block was small enought to |
637 * the stack, then this does nothing. | 639 * have been allocated on the stack (size <= kSize) then this does nothing. |
638 */ | 640 */ |
639 ~SkAutoSMalloc() { | 641 ~SkAutoSMalloc() { |
640 if (fPtr != (void*)fStorage) { | 642 if (fPtr != (void*)fStorage) { |
641 sk_free(fPtr); | 643 sk_free(fPtr); |
642 } | 644 } |
643 } | 645 } |
644 | 646 |
645 /** | 647 /** |
646 * Return the allocated block. May return non-null even if the block is of
zero size. Since | 648 * Return the allocated block. May return non-null even if the block is |
647 * this may be on the stack or dynamically allocated, the caller must not c
all sk_free() on it, | 649 * of zero size. Since this may be on the stack or dynamically allocated, |
648 * but must rely on SkAutoSMalloc to manage it. | 650 * the caller must not call sk_free() on it, but must rely on SkAutoSMalloc |
| 651 * to manage it. |
649 */ | 652 */ |
650 void* get() const { return fPtr; } | 653 void* get() const { return fPtr; } |
651 | 654 |
652 /** | 655 /** |
653 * Return a new block of the requested size, freeing (as necessary) any pre
viously allocated | 656 * Return a new block of the requested size, freeing (as necessary) any |
654 * block. As with the constructor, if size <= kSizeRequested (or slightly m
ore) then the return | 657 * previously allocated block. As with the constructor, if size <= kSize |
655 * block may be allocated locally, rather than from the heap. | 658 * then the return block may be allocated locally, rather than from the |
| 659 * heap. |
656 */ | 660 */ |
657 void* reset(size_t size, | 661 void* reset(size_t size, |
658 SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink, | 662 SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink, |
659 bool* didChangeAlloc = NULL) { | 663 bool* didChangeAlloc = NULL) { |
660 size = (size < kSize) ? kSize : size; | 664 size = (size < kSize) ? kSize : size; |
661 bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink |
| size > fSize); | 665 bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink |
| size > fSize); |
662 if (didChangeAlloc) { | 666 if (didChangeAlloc) { |
663 *didChangeAlloc = alloc; | 667 *didChangeAlloc = alloc; |
664 } | 668 } |
665 if (alloc) { | 669 if (alloc) { |
666 if (fPtr != (void*)fStorage) { | 670 if (fPtr != (void*)fStorage) { |
667 sk_free(fPtr); | 671 sk_free(fPtr); |
668 } | 672 } |
669 | 673 |
670 if (size == kSize) { | 674 if (size == kSize) { |
671 SkASSERT(fPtr != fStorage); // otherwise we lied when setting di
dChangeAlloc. | 675 SkASSERT(fPtr != fStorage); // otherwise we lied when setting di
dChangeAlloc. |
672 fPtr = fStorage; | 676 fPtr = fStorage; |
673 } else { | 677 } else { |
674 fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); | 678 fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP); |
675 } | 679 } |
676 | 680 |
677 fSize = size; | 681 fSize = size; |
678 } | 682 } |
679 SkASSERT(fSize >= size && fSize >= kSize); | 683 SkASSERT(fSize >= size && fSize >= kSize); |
680 SkASSERT((fPtr == fStorage) || fSize > kSize); | 684 SkASSERT((fPtr == fStorage) || fSize > kSize); |
681 return fPtr; | 685 return fPtr; |
682 } | 686 } |
683 | 687 |
684 private: | 688 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 | |
696 void* fPtr; | 689 void* fPtr; |
697 size_t fSize; // can be larger than the requested size (see kReuse) | 690 size_t fSize; // can be larger than the requested size (see kReuse) |
698 uint32_t fStorage[kSize >> 2]; | 691 uint32_t fStorage[(kSize + 3) >> 2]; |
699 }; | 692 }; |
700 // Can't guard the constructor because it's a template class. | 693 // Can't guard the constructor because it's a template class. |
701 | 694 |
702 #endif /* C++ */ | 695 #endif /* C++ */ |
703 | 696 |
704 #endif | 697 #endif |
OLD | NEW |