arraypool.h

Go to the documentation of this file.
00001 #ifndef arraypool_h
00002 #define arraypool_h
00003 
00004 // create and manage a vector of arrays as a memory pool of those arrays
00005 // the idea is to allow the possibility of some extra cache efficiency
00006 
00007 // the chain of ArrayPool
00008 // is only for extra items in a pool_ and no other fields are used.
00009 // The arraypool can be inceased in size by calling grow(ninc) which
00010 // will chain a new ArrayPool of that size. Note that threads using
00011 // distinct ArrayPool chain items will not have a problem with cache
00012 // line sharing.
00013 // When the arraypool needs to grow itself then it
00014 // doubles in size every time a chain ArrayPool is added.
00015 // maxget() tells the most number of arraypool items used at once.
00016 // note that grow_(ninc) implicitly assumes all existing space is in use
00017 // (i.e. put == get) and hence put ends up as put+ninc. On the other
00018 // hand the user callable grow(ninc) assumes NO space is in use,
00019 // so also put == get and put is set back to get.
00020 
00021 #define declareArrayPool(ArrayPool,T) \
00022 class ArrayPool { \
00023 public: \
00024    ArrayPool(long count, long d2); \
00025    ~ArrayPool(); \
00026    T* alloc(); \
00027    void hpfree(T*); \
00028    int maxget() { return maxget_;} \
00029    int size() { return count_;} \
00030    void free_all(); \
00031    T* pool() { return pool_; } \
00032    long get() { return get_; } \
00033    long put() { return put_; } \
00034    long nget() { return nget_; } \
00035    long ntget() { return ntget_; } \
00036    long d2() { return d2_; } \
00037    T* element(long i) { return pool_ + i*d2_; } \
00038    T** items() { return items_; } \
00039    void grow(long ninc); \
00040    ArrayPool* chain() { return chain_; } \
00041    long chain_size() { return pool_size_; } \
00042 private: \
00043    void grow_(long ninc); \
00044 private: \
00045    T** items_; \
00046    T* pool_; \
00047    long pool_size_; \
00048    long count_; \
00049    long get_; \
00050    long put_; \
00051    long nget_; \
00052    long ntget_; \
00053    long maxget_; \
00054    long d2_; \
00055    ArrayPool* chain_; \
00056    ArrayPool* chainlast_; \
00057 }; \
00058  \
00059 
00060 #define implementArrayPool(ArrayPool,T) \
00061 ArrayPool::ArrayPool(long count, long d2) { \
00062    count_ = count; \
00063    d2_ = d2; \
00064    pool_ = (T*)nrn_cacheline_calloc((void**)&pool_, count_*d2_, sizeof(T)); \
00065    pool_size_ = count; \
00066    items_ = new T*[count_]; \
00067    for (long i = 0; i < count_; ++i) { \
00068       items_[i] = pool_ + i*d2_; \
00069    } \
00070    get_ = 0; \
00071    put_ = 0; \
00072    nget_ = 0; \
00073    ntget_ = 0; \
00074    maxget_ = 0; \
00075    chain_ = 0; \
00076    chainlast_ = this; \
00077 } \
00078  \
00079 void ArrayPool::grow(long ninc) { \
00080    grow_(ninc); \
00081    put_ = get_; \
00082 } \
00083  \
00084 void ArrayPool::grow_(long ninc) { \
00085    assert(get_ == put_); \
00086    ArrayPool* p = new ArrayPool(ninc, d2_); \
00087    chainlast_->chain_ = p; \
00088    chainlast_ = p; \
00089    long newcnt = count_ + ninc; \
00090    T** itms = new T*[newcnt]; \
00091    long i, j; \
00092    put_ += ninc; \
00093    for (i = 0; i < get_; ++i) { \
00094       itms[i] = items_[i]; \
00095    } \
00096    for (i = get_, j = 0; j < ninc; ++i, ++j) { \
00097       itms[i] = p->items_[j]; \
00098    } \
00099    for (i = put_, j = get_; j < count_; ++i, ++j) { \
00100       itms[i] = items_[j]; \
00101    } \
00102    delete [] items_; \
00103    delete [] p->items_; \
00104    p->items_ = 0; \
00105    items_ = itms; \
00106    count_ = newcnt; \
00107 } \
00108  \
00109 ArrayPool::~ArrayPool() { \
00110    if (chain_) { \
00111       delete chain_; \
00112    } \
00113    free(pool_); \
00114    if (items_) { \
00115       delete [] items_; \
00116    } \
00117 } \
00118  \
00119 T* ArrayPool::alloc() { \
00120    if (nget_ >= count_) { grow_(count_); } \
00121    T* item = items_[get_]; \
00122    get_ = (get_+1)%count_; \
00123    ++nget_; \
00124    ++ntget_; \
00125    if (nget_ > maxget_) { maxget_ = nget_; } \
00126    return item; \
00127 } \
00128  \
00129 void ArrayPool::hpfree(T* item) { \
00130    assert(nget_ > 0); \
00131    items_[put_] = item; \
00132    put_ = (put_ + 1)%count_; \
00133    --nget_; \
00134 } \
00135  \
00136 void ArrayPool::free_all() { \
00137    ArrayPool* pp; \
00138    long i; \
00139    nget_ = 0; \
00140    get_ = 0; \
00141    put_ = 0; \
00142    for(pp = this; pp; pp = pp->chain_) { \
00143       for (i=0; i < pp->pool_size_; ++i) { \
00144          items_[put_++] = pp->pool_ + i*d2_; \
00145       } \
00146    } \
00147    assert(put_ == count_); \
00148    put_ = 0; \
00149 } \
00150  \
00151 
00152 #endif
Generated on Mon Jun 13 08:10:25 2011 for NEURON by  doxygen 1.6.3