LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkAutoMalloc.h (source / functions) Hit Total Coverage
Test: output.info Lines: 16 43 37.2 %
Date: 2017-07-14 16:53:18 Functions: 6 19 31.6 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2016 Google Inc.
       3             :  *
       4             :  * Use of this source code is governed by a BSD-style license that can be
       5             :  * found in the LICENSE file.
       6             :  */
       7             : 
       8             : #ifndef SkAutoMalloc_DEFINED
       9             : #define SkAutoMalloc_DEFINED
      10             : 
      11             : #include "SkTypes.h"
      12             : #include "SkMalloc.h"
      13             : 
      14             : #include <memory>
      15             : 
      16             : /**
      17             :  *  Manage an allocated block of heap memory. This object is the sole manager of
      18             :  *  the lifetime of the block, so the caller must not call sk_free() or delete
      19             :  *  on the block, unless release() was called.
      20             :  */
      21        2091 : class SkAutoMalloc : SkNoncopyable {
      22             : public:
      23        2091 :     explicit SkAutoMalloc(size_t size = 0)
      24        2091 :         : fPtr(size ? sk_malloc_throw(size) : nullptr), fSize(size) {}
      25             : 
      26             :     /**
      27             :      *  Passed to reset to specify what happens if the requested size is smaller
      28             :      *  than the current size (and the current block was dynamically allocated).
      29             :      */
      30             :     enum OnShrink {
      31             :         /**
      32             :          *  If the requested size is smaller than the current size, and the
      33             :          *  current block is dynamically allocated, free the old block and
      34             :          *  malloc a new block of the smaller size.
      35             :          */
      36             :         kAlloc_OnShrink,
      37             : 
      38             :         /**
      39             :          *  If the requested size is smaller than the current size, and the
      40             :          *  current block is dynamically allocated, just return the old
      41             :          *  block.
      42             :          */
      43             :         kReuse_OnShrink
      44             :     };
      45             : 
      46             :     /**
      47             :      *  Reallocates the block to a new size. The ptr may or may not change.
      48             :      */
      49         190 :     void* reset(size_t size = 0, OnShrink shrink = kAlloc_OnShrink) {
      50         190 :         if (size != fSize && (size > fSize || kReuse_OnShrink != shrink)) {
      51         190 :             fPtr.reset(size ? sk_malloc_throw(size) : nullptr);
      52         190 :             fSize = size;
      53             :         }
      54         190 :         return fPtr.get();
      55             :     }
      56             : 
      57             :     /**
      58             :      *  Return the allocated block.
      59             :      */
      60           0 :     void* get() { return fPtr.get(); }
      61             :     const void* get() const { return fPtr.get(); }
      62             : 
      63             :    /** Transfer ownership of the current ptr to the caller, setting the
      64             :        internal reference to null. Note the caller is reponsible for calling
      65             :        sk_free on the returned address.
      66             :     */
      67           0 :     void* release() {
      68           0 :         fSize = 0;
      69           0 :         return fPtr.release();
      70             :     }
      71             : 
      72             : private:
      73             :     struct WrapFree {
      74         190 :         void operator()(void* p) { sk_free(p); }
      75             :     };
      76             :     std::unique_ptr<void, WrapFree> fPtr;
      77             :     size_t fSize;  // can be larger than the requested size (see kReuse)
      78             : };
      79             : #define SkAutoMalloc(...) SK_REQUIRE_LOCAL_VAR(SkAutoMalloc)
      80             : 
      81             : /**
      82             :  *  Manage an allocated block of memory. If the requested size is <= kSizeRequested (or slightly
      83             :  *  more), then the allocation will come from the stack rather than the heap. This object is the
      84             :  *  sole manager of the lifetime of the block, so the caller must not call sk_free() or delete on
      85             :  *  the block.
      86             :  */
      87             : template <size_t kSizeRequested> class SkAutoSMalloc : SkNoncopyable {
      88             : public:
      89             :     /**
      90             :      *  Creates initially empty storage. get() returns a ptr, but it is to a zero-byte allocation.
      91             :      *  Must call reset(size) to return an allocated block.
      92             :      */
      93         197 :     SkAutoSMalloc() {
      94         197 :         fPtr = fStorage;
      95         197 :         fSize = kSize;
      96         197 :     }
      97             : 
      98             :     /**
      99             :      *  Allocate a block of the specified size. If size <= kSizeRequested (or slightly more), then
     100             :      *  the allocation will come from the stack, otherwise it will be dynamically allocated.
     101             :      */
     102           0 :     explicit SkAutoSMalloc(size_t size) {
     103           0 :         fPtr = fStorage;
     104           0 :         fSize = kSize;
     105           0 :         this->reset(size);
     106           0 :     }
     107             : 
     108             :     /**
     109             :      *  Free the allocated block (if any). If the block was small enough to have been allocated on
     110             :      *  the stack, then this does nothing.
     111             :      */
     112         197 :     ~SkAutoSMalloc() {
     113         197 :         if (fPtr != (void*)fStorage) {
     114           0 :             sk_free(fPtr);
     115             :         }
     116         197 :     }
     117             : 
     118             :     /**
     119             :      *  Return the allocated block. May return non-null even if the block is of zero size. Since
     120             :      *  this may be on the stack or dynamically allocated, the caller must not call sk_free() on it,
     121             :      *  but must rely on SkAutoSMalloc to manage it.
     122             :      */
     123           0 :     void* get() const { return fPtr; }
     124             : 
     125             :     /**
     126             :      *  Return a new block of the requested size, freeing (as necessary) any previously allocated
     127             :      *  block. As with the constructor, if size <= kSizeRequested (or slightly more) then the return
     128             :      *  block may be allocated locally, rather than from the heap.
     129             :      */
     130           0 :     void* reset(size_t size,
     131             :                 SkAutoMalloc::OnShrink shrink = SkAutoMalloc::kAlloc_OnShrink,
     132             :                 bool* didChangeAlloc = nullptr) {
     133           0 :         size = (size < kSize) ? kSize : size;
     134           0 :         bool alloc = size != fSize && (SkAutoMalloc::kAlloc_OnShrink == shrink || size > fSize);
     135           0 :         if (didChangeAlloc) {
     136           0 :             *didChangeAlloc = alloc;
     137             :         }
     138           0 :         if (alloc) {
     139           0 :             if (fPtr != (void*)fStorage) {
     140           0 :                 sk_free(fPtr);
     141             :             }
     142             : 
     143           0 :             if (size == kSize) {
     144           0 :                 SkASSERT(fPtr != fStorage); // otherwise we lied when setting didChangeAlloc.
     145           0 :                 fPtr = fStorage;
     146             :             } else {
     147           0 :                 fPtr = sk_malloc_flags(size, SK_MALLOC_THROW | SK_MALLOC_TEMP);
     148             :             }
     149             : 
     150           0 :             fSize = size;
     151             :         }
     152           0 :         SkASSERT(fSize >= size && fSize >= kSize);
     153           0 :         SkASSERT((fPtr == fStorage) || fSize > kSize);
     154           0 :         return fPtr;
     155             :     }
     156             : 
     157             : private:
     158             :     // Align up to 32 bits.
     159             :     static const size_t kSizeAlign4 = SkAlign4(kSizeRequested);
     160             : #if defined(GOOGLE3)
     161             :     // Stack frame size is limited for GOOGLE3. 4k is less than the actual max, but some functions
     162             :     // have multiple large stack allocations.
     163             :     static const size_t kMaxBytes = 4 * 1024;
     164             :     static const size_t kSize = kSizeRequested > kMaxBytes ? kMaxBytes : kSizeAlign4;
     165             : #else
     166             :     static const size_t kSize = kSizeAlign4;
     167             : #endif
     168             : 
     169             :     void*       fPtr;
     170             :     size_t      fSize;  // can be larger than the requested size (see kReuse)
     171             :     uint32_t    fStorage[kSize >> 2];
     172             : };
     173             : // Can't guard the constructor because it's a template class.
     174             : 
     175             : #endif

Generated by: LCOV version 1.13