NEURON
arraypool.h
Go to the documentation of this file.
1 #pragma once
2 #include "oc_ansi.h" // nrn_cacheline_calloc
3 
4 // create and manage a vector of arrays as a memory pool of those arrays
5 // the idea is to allow the possibility of some extra cache efficiency
6 
7 // the chain of ArrayPool
8 // is only for extra items in a pool_ and no other fields are used.
9 // The arraypool can be inceased in size by calling grow(ninc) which
10 // will chain a new ArrayPool of that size. Note that threads using
11 // distinct ArrayPool chain items will not have a problem with cache
12 // line sharing.
13 // When the arraypool needs to grow itself then it
14 // doubles in size every time a chain ArrayPool is added.
15 // maxget() tells the most number of arraypool items used at once.
16 // note that grow_(ninc) implicitly assumes all existing space is in use
17 // (i.e. put == get) and hence put ends up as put+ninc. On the other
18 // hand the user callable grow(ninc) assumes NO space is in use,
19 // so also put == get and put is set back to get.
20 
21 template <typename T>
22 class ArrayPool {
23  public:
24  ArrayPool(long count, long d2);
25  ~ArrayPool();
26  T* alloc();
27  void hpfree(T*);
28  int maxget() {
29  return maxget_;
30  }
31  int size() {
32  return count_;
33  }
34  void free_all();
35  T* pool() {
36  return pool_;
37  }
38  long get() {
39  return get_;
40  }
41  long put() {
42  return put_;
43  }
44  long nget() {
45  return nget_;
46  }
47  long ntget() {
48  return ntget_;
49  }
50  long d2() {
51  return d2_;
52  }
53  T* element(long i) {
54  return pool_ + i * d2_;
55  }
56  T** items() {
57  return items_;
58  }
59  void grow(long ninc);
61  return chain_;
62  }
63  long chain_size() {
64  return pool_size_;
65  }
66 
67  private:
68  void grow_(long ninc);
69 
70  private:
71  T** items_;
72  T* pool_;
73  long pool_size_;
74  long count_;
75  long get_;
76  long put_;
77  long nget_;
78  long ntget_;
79  long maxget_;
80  long d2_;
83 };
84 
85 
86 template <typename T>
87 ArrayPool<T>::ArrayPool(long count, long d2) {
88  count_ = count;
89  d2_ = d2;
90  pool_ = (T*) nrn_cacheline_calloc((void**) &pool_, count_ * d2_, sizeof(T));
91  pool_size_ = count;
92  items_ = new T*[count_];
93  for (long i = 0; i < count_; ++i) {
94  items_[i] = pool_ + i * d2_;
95  }
96  get_ = 0;
97  put_ = 0;
98  nget_ = 0;
99  ntget_ = 0;
100  maxget_ = 0;
101  chain_ = 0;
102  chainlast_ = this;
103 }
104 
105 template <typename T>
106 void ArrayPool<T>::grow(long ninc) {
107  grow_(ninc);
108  put_ = get_;
109 }
110 
111 template <typename T>
112 void ArrayPool<T>::grow_(long ninc) {
113  assert(get_ == put_);
114  ArrayPool* p = new ArrayPool(ninc, d2_);
115  chainlast_->chain_ = p;
116  chainlast_ = p;
117  long newcnt = count_ + ninc;
118  T** itms = new T*[newcnt];
119  long i, j;
120  put_ += ninc;
121  for (i = 0; i < get_; ++i) {
122  itms[i] = items_[i];
123  }
124  for (i = get_, j = 0; j < ninc; ++i, ++j) {
125  itms[i] = p->items_[j];
126  }
127  for (i = put_, j = get_; j < count_; ++i, ++j) {
128  itms[i] = items_[j];
129  }
130  delete[] items_;
131  delete[] p->items_;
132  p->items_ = 0;
133  items_ = itms;
134  count_ = newcnt;
135 }
136 
137 template <typename T>
139  if (chain_) {
140  delete chain_;
141  }
142  free(pool_);
143  if (items_) {
144  delete[] items_;
145  }
146 }
147 
148 template <typename T>
150  if (nget_ >= count_) {
151  grow_(count_);
152  }
153  T* item = items_[get_];
154  get_ = (get_ + 1) % count_;
155  ++nget_;
156  ++ntget_;
157  if (nget_ > maxget_) {
158  maxget_ = nget_;
159  }
160  return item;
161 }
162 
163 template <typename T>
164 void ArrayPool<T>::hpfree(T* item) {
165  assert(nget_ > 0);
166  items_[put_] = item;
167  put_ = (put_ + 1) % count_;
168  --nget_;
169 }
170 
171 template <typename T>
173  ArrayPool* pp;
174  long i;
175  nget_ = 0;
176  get_ = 0;
177  put_ = 0;
178  for (pp = this; pp; pp = pp->chain_) {
179  for (i = 0; i < pp->pool_size_; ++i) {
180  items_[put_++] = pp->pool_ + i * d2_;
181  }
182  }
183  assert(put_ == count_);
184  put_ = 0;
185 }
long get()
Definition: arraypool.h:38
T ** items()
Definition: arraypool.h:56
long chain_size()
Definition: arraypool.h:63
long d2()
Definition: arraypool.h:50
ArrayPool(long count, long d2)
Definition: arraypool.h:87
void grow(long ninc)
Definition: arraypool.h:106
void hpfree(T *)
Definition: arraypool.h:164
int maxget()
Definition: arraypool.h:28
long put()
Definition: arraypool.h:41
long maxget_
Definition: arraypool.h:79
ArrayPool * chainlast_
Definition: arraypool.h:82
long pool_size_
Definition: arraypool.h:73
T * element(long i)
Definition: arraypool.h:53
T * alloc()
Definition: arraypool.h:149
long ntget()
Definition: arraypool.h:47
long get_
Definition: arraypool.h:75
long nget_
Definition: arraypool.h:77
T * pool_
Definition: arraypool.h:72
void free_all()
Definition: arraypool.h:172
long d2_
Definition: arraypool.h:80
~ArrayPool()
Definition: arraypool.h:138
long count_
Definition: arraypool.h:74
long nget()
Definition: arraypool.h:44
long put_
Definition: arraypool.h:76
T * pool()
Definition: arraypool.h:35
ArrayPool * chain()
Definition: arraypool.h:60
int size()
Definition: arraypool.h:31
void grow_(long ninc)
Definition: arraypool.h:112
ArrayPool * chain_
Definition: arraypool.h:81
long ntget_
Definition: arraypool.h:78
T ** items_
Definition: arraypool.h:71
#define i
Definition: md1redef.h:19
#define assert(ex)
Definition: hocassrt.h:24
size_t p
size_t j
void * nrn_cacheline_calloc(void **memptr, std::size_t nmemb, std::size_t size)
Definition: memory.cpp:103
HOC interpreter function declarations (included by hocdec.h)