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