Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2014 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 SkFreeList_DEFINED
      9 #define SkFreeList_DEFINED
     10 
     11 #include "SkTInternalSList.h"
     12 
     13 /**
     14  * An implementation of a self growing pool of objects.
     15  * It maintains a pool of fully initialized objects. If an attempt is made to
     16  * acquire one, and there are none left, it makes some more.
     17  * It does not automatically reclaim them, they have to be given back to it.
     18  * Constructors will be called on objects allocated by the pool at allocation
     19  * time.
     20  * All allocated objects will be destroyed and memory will be reclaimed when
     21  * the pool is destroyed, so the pool must survive longer than you are using
     22  * any item taken from it.
     23  */
     24 template<typename T, int numItemsPerBlock = 4096/sizeof(T)> class SkTObjectPool {
     25 public:
     26     SkTObjectPool() {}
     27     ~SkTObjectPool() {
     28         while (!fBlocks.isEmpty()) {
     29             SkDELETE(fBlocks.pop());
     30         }
     31     }
     32 
     33     /**
     34      * Get an item from the pool.
     35      * If the pool has no free items, it will allocate and construct some more.
     36      * The returned item is only valid as long as the pool has not been
     37      * destroyed, at that point all memory allocated by grow will have been
     38      * reclaimed.
     39      * This method is *not* thread safe.
     40      */
     41     T* acquire() {
     42         if (fAvailable.isEmpty()) {
     43             grow();
     44         }
     45         return fAvailable.pop();
     46     }
     47 
     48     /**
     49      * Release an item into the pool.
     50      * The item does not have to have come from the pool, but if it did not
     51      * it must have a lifetime greater than the pool does.
     52      * This method is *not* thread safe.
     53      */
     54     void release(T* entry) {
     55         fAvailable.push(entry);
     56     }
     57 
     58     /**
     59      * Takes all the items from an SkTInternalSList and adds them back to this
     60      * pool. The other list will be left empty.
     61      */
     62     void releaseAll(SkTInternalSList<T>* other) {
     63         fAvailable.pushAll(other);
     64     }
     65 
     66     /**
     67      * Returns the number of items immediately available without having to
     68      * construct any new ones.
     69      */
     70     int available() const { return fAvailable.getCount(); }
     71 
     72     /**
     73      * Returns the number of blocks of items the pool has allocated so far.
     74      */
     75     int blocks() const { return fBlocks.getCount(); }
     76 
     77     /**
     78      * Returns the number of items allocated by the pool in total.
     79      */
     80     int allocated() const { return fBlocks.getCount() * numItemsPerBlock; }
     81 
     82 private:
     83     /**
     84      * The type for a new block of entries for the list.
     85      */
     86     struct Block {
     87         T entries[numItemsPerBlock];
     88         SK_DECLARE_INTERNAL_SLIST_INTERFACE(Block);
     89     };
     90     SkTInternalSList<Block> fBlocks;
     91     SkTInternalSList<T> fAvailable;
     92 
     93     /**
     94      * When the free list runs out of items, this method is called to allocate
     95      * a new block of them.
     96      * It calls the constructors and then pushes the nodes into the available
     97      * list.
     98      */
     99     void grow() {
    100         Block* block = SkNEW(Block);
    101         fBlocks.push(block);
    102         for(int index = 0; index < numItemsPerBlock; ++index) {
    103             fAvailable.push(&block->entries[index]);
    104         }
    105     }
    106 
    107 };
    108 
    109 #endif
    110