LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/gpu - GrAllocator.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 74 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 44 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2010 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 GrAllocator_DEFINED
       9             : #define GrAllocator_DEFINED
      10             : 
      11             : #include "GrConfig.h"
      12             : #include "GrTypes.h"
      13             : #include "SkTArray.h"
      14             : #include "SkTypes.h"
      15             : 
      16             : class GrAllocator : SkNoncopyable {
      17             : public:
      18           0 :     ~GrAllocator() { this->reset(); }
      19             : 
      20             :     /**
      21             :      * Create an allocator
      22             :      *
      23             :      * @param   itemSize        the size of each item to allocate
      24             :      * @param   itemsPerBlock   the number of items to allocate at once
      25             :      * @param   initialBlock    optional memory to use for the first block.
      26             :      *                          Must be at least itemSize*itemsPerBlock sized.
      27             :      *                          Caller is responsible for freeing this memory.
      28             :      */
      29           0 :     GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock)
      30           0 :         : fItemSize(itemSize)
      31             :         , fItemsPerBlock(itemsPerBlock)
      32           0 :         , fOwnFirstBlock(nullptr == initialBlock)
      33             :         , fCount(0)
      34           0 :         , fInsertionIndexInBlock(0) {
      35           0 :         SkASSERT(itemsPerBlock > 0);
      36           0 :         fBlockSize = fItemSize * fItemsPerBlock;
      37           0 :         if (fOwnFirstBlock) {
      38             :             // This force us to allocate a new block on push_back().
      39           0 :             fInsertionIndexInBlock = fItemsPerBlock;
      40             :         } else {
      41           0 :             fBlocks.push_back() = initialBlock;
      42           0 :             fInsertionIndexInBlock = 0;
      43             :         }
      44           0 :     }
      45             : 
      46             :     /**
      47             :      * Adds an item and returns pointer to it.
      48             :      *
      49             :      * @return pointer to the added item.
      50             :      */
      51           0 :     void* push_back() {
      52             :         // we always have at least one block
      53           0 :         if (fItemsPerBlock == fInsertionIndexInBlock) {
      54           0 :             fBlocks.push_back() = sk_malloc_throw(fBlockSize);
      55           0 :             fInsertionIndexInBlock = 0;
      56             :         }
      57           0 :         void* ret = (char*)fBlocks.back() + fItemSize * fInsertionIndexInBlock;
      58           0 :         ++fCount;
      59           0 :         ++fInsertionIndexInBlock;
      60           0 :         return ret;
      61             :     }
      62             : 
      63             :     /**
      64             :      * Remove the last item, only call if count() != 0
      65             :      */
      66             :     void pop_back() {
      67             :         SkASSERT(fCount);
      68             :         SkASSERT(fInsertionIndexInBlock > 0);
      69             :         --fInsertionIndexInBlock;
      70             :         --fCount;
      71             :         if (0 == fInsertionIndexInBlock) {
      72             :             // Never delete the first block
      73             :             if (fBlocks.count() > 1) {
      74             :                 sk_free(fBlocks.back());
      75             :                 fBlocks.pop_back();
      76             :                 fInsertionIndexInBlock = fItemsPerBlock;
      77             :             }
      78             :         }
      79             :     }
      80             : 
      81             :     /**
      82             :      * Removes all added items.
      83             :      */
      84           0 :     void reset() {
      85           0 :         int firstBlockToFree = fOwnFirstBlock ? 0 : 1;
      86           0 :         for (int i = firstBlockToFree; i < fBlocks.count(); ++i) {
      87           0 :             sk_free(fBlocks[i]);
      88             :         }
      89           0 :         if (fOwnFirstBlock) {
      90           0 :             fBlocks.reset();
      91             :             // This force us to allocate a new block on push_back().
      92           0 :             fInsertionIndexInBlock = fItemsPerBlock;
      93             :         } else {
      94           0 :             fBlocks.pop_back_n(fBlocks.count() - 1);
      95           0 :             fInsertionIndexInBlock = 0;
      96             :         }
      97           0 :         fCount = 0;
      98           0 :     }
      99             : 
     100             :     /**
     101             :      * Returns the item count.
     102             :      */
     103           0 :     int count() const {
     104           0 :         return fCount;
     105             :     }
     106             : 
     107             :     /**
     108             :      * Is the count 0?
     109             :      */
     110           0 :     bool empty() const { return 0 == fCount; }
     111             : 
     112             :     /**
     113             :      * Access last item, only call if count() != 0
     114             :      */
     115           0 :     void* back() {
     116           0 :         SkASSERT(fCount);
     117           0 :         SkASSERT(fInsertionIndexInBlock > 0);
     118           0 :         return (char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fItemSize;
     119             :     }
     120             : 
     121             :     /**
     122             :      * Access last item, only call if count() != 0
     123             :      */
     124             :     const void* back() const {
     125             :         SkASSERT(fCount);
     126             :         SkASSERT(fInsertionIndexInBlock > 0);
     127             :         return (const char*)(fBlocks.back()) + (fInsertionIndexInBlock - 1) * fItemSize;
     128             :     }
     129             : 
     130             :     /**
     131             :      * Iterates through the allocator. This is faster than using operator[] when walking linearly
     132             :      * through the allocator.
     133             :      */
     134             :     class Iter {
     135             :     public:
     136             :         /**
     137             :          * Initializes the iterator. next() must be called before get().
     138             :          */
     139             :         Iter(const GrAllocator* allocator)
     140             :             : fAllocator(allocator)
     141             :             , fBlockIndex(-1)
     142             :             , fIndexInBlock(allocator->fItemsPerBlock - 1)
     143             :             , fItemIndex(-1) {}
     144             : 
     145             :         /**
     146             :          * Advances the iterator. Iteration is finished when next() returns false.
     147             :          */
     148             :         bool next() {
     149             :             ++fIndexInBlock;
     150             :             ++fItemIndex;
     151             :             if (fIndexInBlock == fAllocator->fItemsPerBlock) {
     152             :                 ++fBlockIndex;
     153             :                 fIndexInBlock = 0;
     154             :             }
     155             :             return fItemIndex < fAllocator->fCount;
     156             :         }
     157             : 
     158             :         /**
     159             :          * Gets the current iterator value. Call next() at least once before calling. Don't call
     160             :          * after next() returns false.
     161             :          */
     162             :         void* get() const {
     163             :             SkASSERT(fItemIndex >= 0 && fItemIndex < fAllocator->fCount);
     164             :             return (char*) fAllocator->fBlocks[fBlockIndex] + fIndexInBlock * fAllocator->fItemSize;
     165             :         }
     166             : 
     167             :     private:
     168             :         const GrAllocator* fAllocator;
     169             :         int                fBlockIndex;
     170             :         int                fIndexInBlock;
     171             :         int                fItemIndex;
     172             :     };
     173             : 
     174             :     /**
     175             :      * Access item by index.
     176             :      */
     177           0 :     void* operator[] (int i) {
     178           0 :         SkASSERT(i >= 0 && i < fCount);
     179           0 :         return (char*)fBlocks[i / fItemsPerBlock] +
     180           0 :                fItemSize * (i % fItemsPerBlock);
     181             :     }
     182             : 
     183             :     /**
     184             :      * Access item by index.
     185             :      */
     186           0 :     const void* operator[] (int i) const {
     187           0 :         SkASSERT(i >= 0 && i < fCount);
     188           0 :         return (const char*)fBlocks[i / fItemsPerBlock] +
     189           0 :                fItemSize * (i % fItemsPerBlock);
     190             :     }
     191             : 
     192             : protected:
     193             :     /**
     194             :      * Set first block of memory to write into.  Must be called before any other methods.
     195             :      * This requires that you have passed nullptr in the constructor.
     196             :      *
     197             :      * @param   initialBlock    optional memory to use for the first block.
     198             :      *                          Must be at least itemSize*itemsPerBlock sized.
     199             :      *                          Caller is responsible for freeing this memory.
     200             :      */
     201             :     void setInitialBlock(void* initialBlock) {
     202             :         SkASSERT(0 == fCount);
     203             :         SkASSERT(0 == fBlocks.count());
     204             :         SkASSERT(fItemsPerBlock == fInsertionIndexInBlock);
     205             :         fOwnFirstBlock = false;
     206             :         fBlocks.push_back() = initialBlock;
     207             :         fInsertionIndexInBlock = 0;
     208             :     }
     209             : 
     210             :     // For access to above function.
     211             :     template <typename T> friend class GrTAllocator;
     212             : 
     213             : private:
     214             :     static const int NUM_INIT_BLOCK_PTRS = 8;
     215             : 
     216             :     SkSTArray<NUM_INIT_BLOCK_PTRS, void*, true>   fBlocks;
     217             :     size_t                                        fBlockSize;
     218             :     size_t                                        fItemSize;
     219             :     int                                           fItemsPerBlock;
     220             :     bool                                          fOwnFirstBlock;
     221             :     int                                           fCount;
     222             :     int                                           fInsertionIndexInBlock;
     223             : 
     224             :     typedef SkNoncopyable INHERITED;
     225             : };
     226             : 
     227             : template <typename T> class GrTAllocator;
     228             : template <typename T> void* operator new(size_t, GrTAllocator<T>*);
     229             : 
     230             : template <typename T> class GrTAllocator : SkNoncopyable {
     231             : public:
     232           0 :     virtual ~GrTAllocator() { this->reset(); }
     233             : 
     234             :     /**
     235             :      * Create an allocator
     236             :      *
     237             :      * @param   itemsPerBlock   the number of items to allocate at once
     238             :      */
     239           0 :     explicit GrTAllocator(int itemsPerBlock)
     240           0 :         : fAllocator(sizeof(T), itemsPerBlock, nullptr) {}
     241             : 
     242             :     /**
     243             :      * Adds an item and returns it.
     244             :      *
     245             :      * @return the added item.
     246             :      */
     247           0 :     T& push_back() {
     248           0 :         void* item = fAllocator.push_back();
     249           0 :         SkASSERT(item);
     250           0 :         new (item) T;
     251           0 :         return *(T*)item;
     252             :     }
     253             : 
     254           0 :     T& push_back(const T& t) {
     255           0 :         void* item = fAllocator.push_back();
     256           0 :         SkASSERT(item);
     257           0 :         new (item) T(t);
     258           0 :         return *(T*)item;
     259             :     }
     260             : 
     261             :     template <typename... Args> T& emplace_back(Args&&... args) {
     262             :         void* item = fAllocator.push_back();
     263             :         SkASSERT(item);
     264             :         new (item) T(std::forward<Args>(args)...);
     265             :         return *(T*)item;
     266             :     }
     267             : 
     268             :     /**
     269             :      * Remove the last item, only call if count() != 0
     270             :      */
     271             :     void pop_back() {
     272             :         this->back().~T();
     273             :         fAllocator.pop_back();
     274             :     }
     275             : 
     276             :     /**
     277             :      * Removes all added items.
     278             :      */
     279           0 :     void reset() {
     280           0 :         int c = fAllocator.count();
     281           0 :         for (int i = 0; i < c; ++i) {
     282           0 :             ((T*)fAllocator[i])->~T();
     283             :         }
     284           0 :         fAllocator.reset();
     285           0 :     }
     286             : 
     287             :     /**
     288             :      * Returns the item count.
     289             :      */
     290           0 :     int count() const {
     291           0 :         return fAllocator.count();
     292             :     }
     293             : 
     294             :     /**
     295             :      * Is the count 0?
     296             :      */
     297           0 :     bool empty() const { return fAllocator.empty(); }
     298             : 
     299             :     /**
     300             :      * Access last item, only call if count() != 0
     301             :      */
     302           0 :     T& back() {
     303           0 :         return *(T*)fAllocator.back();
     304             :     }
     305             : 
     306             :     /**
     307             :      * Access last item, only call if count() != 0
     308             :      */
     309             :     const T& back() const {
     310             :         return *(const T*)fAllocator.back();
     311             :     }
     312             : 
     313             :     /**
     314             :      * Iterates through the allocator. This is faster than using operator[] when walking linearly
     315             :      * through the allocator.
     316             :      */
     317             :     class Iter {
     318             :     public:
     319             :         /**
     320             :          * Initializes the iterator. next() must be called before get() or ops * and ->.
     321             :          */
     322             :         Iter(const GrTAllocator* allocator) : fImpl(&allocator->fAllocator) {}
     323             : 
     324             :         /**
     325             :          * Advances the iterator. Iteration is finished when next() returns false.
     326             :          */
     327             :         bool next() { return fImpl.next(); }
     328             : 
     329             :         /**
     330             :          * Gets the current iterator value. Call next() at least once before calling. Don't call
     331             :          * after next() returns false.
     332             :          */
     333             :         T* get() const { return (T*) fImpl.get(); }
     334             : 
     335             :         /**
     336             :          * Convenience operators. Same rules for calling apply as get().
     337             :          */
     338             :         T& operator*() const { return *this->get(); }
     339             :         T* operator->() const { return this->get(); }
     340             : 
     341             :     private:
     342             :         GrAllocator::Iter fImpl;
     343             :     };
     344             : 
     345             :     /**
     346             :      * Access item by index.
     347             :      */
     348           0 :     T& operator[] (int i) {
     349           0 :         return *(T*)(fAllocator[i]);
     350             :     }
     351             : 
     352             :     /**
     353             :      * Access item by index.
     354             :      */
     355           0 :     const T& operator[] (int i) const {
     356           0 :         return *(const T*)(fAllocator[i]);
     357             :     }
     358             : 
     359             : protected:
     360             :     /*
     361             :      * Set first block of memory to write into.  Must be called before any other methods.
     362             :      *
     363             :      * @param   initialBlock    optional memory to use for the first block.
     364             :      *                          Must be at least size(T)*itemsPerBlock sized.
     365             :      *                          Caller is responsible for freeing this memory.
     366             :      */
     367             :     void setInitialBlock(void* initialBlock) {
     368             :         fAllocator.setInitialBlock(initialBlock);
     369             :     }
     370             : 
     371             : private:
     372             :     friend void* operator new<T>(size_t, GrTAllocator*);
     373             : 
     374             :     GrAllocator fAllocator;
     375             :     typedef SkNoncopyable INHERITED;
     376             : };
     377             : 
     378             : template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
     379             : private:
     380             :     typedef GrTAllocator<T> INHERITED;
     381             : 
     382             : public:
     383             :     GrSTAllocator() : INHERITED(N) {
     384             :         this->setInitialBlock(fStorage.get());
     385             :     }
     386             : 
     387             : private:
     388             :     SkAlignedSTStorage<N, T> fStorage;
     389             : };
     390             : 
     391             : template <typename T> void* operator new(size_t size, GrTAllocator<T>* allocator) {
     392             :     return allocator->fAllocator.push_back();
     393             : }
     394             : 
     395             : // Skia doesn't use C++ exceptions but it may be compiled with them enabled. Having an op delete
     396             : // to match the op new silences warnings about missing op delete when a constructor throws an
     397             : // exception.
     398             : template <typename T> void operator delete(void*, GrTAllocator<T>*) {
     399             :     SK_ABORT("Invalid Operation");
     400             : }
     401             : 
     402             : #define GrNEW_APPEND_TO_ALLOCATOR(allocator_ptr, type_name, args) \
     403             :     new (allocator_ptr) type_name args
     404             : 
     405             : #endif

Generated by: LCOV version 1.13