Home | History | Annotate | Download | only in gpu
      1 
      2 /*
      3  * Copyright 2010 Google Inc.
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 
     11 #ifndef GrAllocator_DEFINED
     12 #define GrAllocator_DEFINED
     13 
     14 #include "GrConfig.h"
     15 #include "SkTArray.h"
     16 
     17 class GrAllocator : GrNoncopyable {
     18 public:
     19     ~GrAllocator() {
     20         reset();
     21     }
     22 
     23     /**
     24      * Create an allocator
     25      *
     26      * @param   itemSize        the size of each item to allocate
     27      * @param   itemsPerBlock   the number of items to allocate at once
     28      * @param   initialBlock    optional memory to use for the first block.
     29      *                          Must be at least itemSize*itemsPerBlock sized.
     30      *                          Caller is responsible for freeing this memory.
     31      */
     32     GrAllocator(size_t itemSize, int itemsPerBlock, void* initialBlock) :
     33             fItemSize(itemSize),
     34             fItemsPerBlock(itemsPerBlock),
     35             fOwnFirstBlock(NULL == initialBlock),
     36             fCount(0) {
     37         GrAssert(itemsPerBlock > 0);
     38         fBlockSize = fItemSize * fItemsPerBlock;
     39         fBlocks.push_back() = initialBlock;
     40         GR_DEBUGCODE(if (!fOwnFirstBlock) {*((char*)initialBlock+fBlockSize-1)='a';} );
     41     }
     42 
     43     /**
     44      * Adds an item and returns pointer to it.
     45      *
     46      * @return pointer to the added item.
     47      */
     48     void* push_back() {
     49         int indexInBlock = fCount % fItemsPerBlock;
     50         // we always have at least one block
     51         if (0 == indexInBlock) {
     52             if (0 != fCount) {
     53                 fBlocks.push_back() = GrMalloc(fBlockSize);
     54             } else if (fOwnFirstBlock) {
     55                 fBlocks[0] = GrMalloc(fBlockSize);
     56             }
     57         }
     58         void* ret = (char*)fBlocks[fCount/fItemsPerBlock] +
     59                     fItemSize * indexInBlock;
     60         ++fCount;
     61         return ret;
     62     }
     63 
     64     /**
     65      * removes all added items
     66      */
     67     void reset() {
     68         int blockCount = GrMax((unsigned)1,
     69                                GrUIDivRoundUp(fCount, fItemsPerBlock));
     70         for (int i = 1; i < blockCount; ++i) {
     71             GrFree(fBlocks[i]);
     72         }
     73         if (fOwnFirstBlock) {
     74             GrFree(fBlocks[0]);
     75             fBlocks[0] = NULL;
     76         }
     77         fBlocks.pop_back_n(blockCount-1);
     78         fCount = 0;
     79     }
     80 
     81     /**
     82      * count of items
     83      */
     84     int count() const {
     85         return fCount;
     86     }
     87 
     88     /**
     89      * is the count 0
     90      */
     91     bool empty() const { return fCount == 0; }
     92 
     93     /**
     94      * access last item, only call if count() != 0
     95      */
     96     void* back() {
     97         GrAssert(fCount);
     98         return (*this)[fCount-1];
     99     }
    100 
    101     /**
    102      * access last item, only call if count() != 0
    103      */
    104     const void* back() const {
    105         GrAssert(fCount);
    106         return (*this)[fCount-1];
    107     }
    108 
    109     /**
    110      * access item by index.
    111      */
    112     void* operator[] (int i) {
    113         GrAssert(i >= 0 && i < fCount);
    114         return (char*)fBlocks[i / fItemsPerBlock] +
    115                fItemSize * (i % fItemsPerBlock);
    116     }
    117 
    118     /**
    119      * access item by index.
    120      */
    121     const void* operator[] (int i) const {
    122         GrAssert(i >= 0 && i < fCount);
    123         return (const char*)fBlocks[i / fItemsPerBlock] +
    124                fItemSize * (i % fItemsPerBlock);
    125     }
    126 
    127 private:
    128     static const int NUM_INIT_BLOCK_PTRS = 8;
    129 
    130     SkSTArray<NUM_INIT_BLOCK_PTRS, void*>   fBlocks;
    131     size_t                                  fBlockSize;
    132     size_t                                  fItemSize;
    133     int                                     fItemsPerBlock;
    134     bool                                    fOwnFirstBlock;
    135     int                                     fCount;
    136 
    137     typedef GrNoncopyable INHERITED;
    138 };
    139 
    140 template <typename T>
    141 class GrTAllocator : GrNoncopyable {
    142 
    143 public:
    144     virtual ~GrTAllocator() { this->reset(); };
    145 
    146     /**
    147      * Create an allocator
    148      *
    149      * @param   itemsPerBlock   the number of items to allocate at once
    150      * @param   initialBlock    optional memory to use for the first block.
    151      *                          Must be at least size(T)*itemsPerBlock sized.
    152      *                          Caller is responsible for freeing this memory.
    153      */
    154     explicit GrTAllocator(int itemsPerBlock)
    155         : fAllocator(sizeof(T), itemsPerBlock, NULL) {}
    156 
    157     /**
    158      * Adds an item and returns it.
    159      *
    160      * @return the added item.
    161      */
    162     T& push_back() {
    163         void* item = fAllocator.push_back();
    164         GrAssert(NULL != item);
    165         new (item) T;
    166         return *(T*)item;
    167     }
    168 
    169     T& push_back(const T& t) {
    170         void* item = fAllocator.push_back();
    171         GrAssert(NULL != item);
    172         new (item) T(t);
    173         return *(T*)item;
    174     }
    175 
    176     /**
    177      * removes all added items
    178      */
    179     void reset() {
    180         int c = fAllocator.count();
    181         for (int i = 0; i < c; ++i) {
    182             ((T*)fAllocator[i])->~T();
    183         }
    184         fAllocator.reset();
    185     }
    186 
    187     /**
    188      * count of items
    189      */
    190     int count() const {
    191         return fAllocator.count();
    192     }
    193 
    194     /**
    195      * is the count 0
    196      */
    197     bool empty() const { return fAllocator.empty(); }
    198 
    199     /**
    200      * access last item, only call if count() != 0
    201      */
    202     T& back() {
    203         return *(T*)fAllocator.back();
    204     }
    205 
    206     /**
    207      * access last item, only call if count() != 0
    208      */
    209     const T& back() const {
    210         return *(const T*)fAllocator.back();
    211     }
    212 
    213     /**
    214      * access item by index.
    215      */
    216     T& operator[] (int i) {
    217         return *(T*)(fAllocator[i]);
    218     }
    219 
    220     /**
    221      * access item by index.
    222      */
    223     const T& operator[] (int i) const {
    224         return *(const T*)(fAllocator[i]);
    225     }
    226 
    227 protected:
    228     GrTAllocator(int itemsPerBlock, void* initialBlock)
    229         : fAllocator(sizeof(T), itemsPerBlock, initialBlock) {
    230     }
    231 
    232 private:
    233     GrAllocator fAllocator;
    234     typedef GrNoncopyable INHERITED;
    235 };
    236 
    237 template <int N, typename T> class GrSTAllocator : public GrTAllocator<T> {
    238 private:
    239     typedef GrTAllocator<T> INHERITED;
    240 
    241 public:
    242     GrSTAllocator() : INHERITED(N, fStorage.get()) {
    243     }
    244 
    245 private:
    246     SkAlignedSTStorage<N, T> fStorage;
    247 };
    248 
    249 #endif
    250