EpcTools
An event based multi-threaded C++ development framework.
ememory.h
Go to the documentation of this file.
1 /*
2 * Copyright (c) 2020 Sprint
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 
17 #ifndef __EMEMORY_H
18 #define __EMEMORY_H
19 
22 
23 #include "eerror.h"
24 #include "esynch.h"
25 #include "etime.h"
26 
27 DECLARE_ERROR(EMemory_NodeSizeTooSmall);
28 
29 class EMemory
30 {
31 public:
32  class Pool;
33 
34  class Block
35  {
36  friend Pool;
37  public:
39  : next_(nullptr)
40 #ifdef EMEMORY_STATISTICS
41  , cnt_(0)
42 #endif
43  {
44  }
45 
46  Block *next() { return next_; }
47  pUChar data() { return data_; }
48 
49 #ifdef EMEMORY_STATISTICS
50  const ETime &lastAllocated() const { return last_; }
51  size_t ccount() const { return cnt_; }
52  protected:
53  Void allocate()
54  {
55  last_ = ETime::Now();
56  cnt_++;
57  }
58 #endif
59 
60  protected:
61  Block &next(Block *nxt) { next_ = nxt; return *this; }
62 
63  private:
64  Block *next_;
65 #ifdef EMEMORY_STATISTICS
66  ETime last_; // the last time the block was allocated
67  size_t cnt_; // the number of times this block has been allocated
68 #endif
69  UChar data_[0];
70  };
71 
72  class Node
73  {
74  friend Pool;
75  public:
76  Node(Pool &pool) : pool_(pool), next_(nullptr) {}
77 
78  Pool &pool() { return pool_; }
79  Node *next() { return next_; }
80  pUChar data() { return data_; }
81 
82  protected:
83  Node &next(Node *nxt) { next_ = nxt; return *this; }
84 
85  private:
86  Node();
87  Pool &pool_;
88  Node *next_;
89  UChar data_[0];
90  };
91 
92  class Pool
93  {
94  public:
95  Pool(size_t allocSize=0, size_t nodeSize=0, size_t blockCount=0)
96  : head_(nullptr),
97  free_(nullptr),
98  as_(allocSize),
99  ns_(nodeSize),
100  bs_(0),
101  bc_(blockCount)
102  {
103  setSize();
104  }
106  {
107  while (head_)
108  {
109  Node *nxt = head_->next();
110  delete [] reinterpret_cast<pUChar>(head_);
111  head_ = nxt;
112  }
113  }
114 
115  size_t allocSize() const { return as_; }
116  size_t blockSize() const { return bs_; }
117  size_t blockCount() const { return bc_; }
118  size_t nodeSize() const { return ns_; }
119 
120  Pool &setSize(size_t as, size_t ns, size_t bc=0)
121  {
122  as_ = as;
123  ns_ = ns;
124  bc_ = bc;
125  setSize();
126  return *this;
127  }
128 
129  pVoid allocate()
130  {
131  EMutexLock l(mutex_);
132  if (!free_)
133  {
134  pUChar mem = new UChar[ns_];
135  Node *n = new (mem) Node(*this);
136  pUChar data = n->data();
137  for (size_t i=0; i<bc_; i++)
138  {
139  Block *blk = new (data) Block();
140  blk->next(free_);
141  free_ = blk;
142  data += bs_;
143  }
144  }
145  Block *blk = free_;
146  free_ = blk->next();
147 #ifdef EMEMORY_STATISTICS
148  blk->allocate();
149 #endif
150  return blk->data();
151  }
152 
153  Void deallocate(pVoid data)
154  {
155  EMutexLock l(mutex_);
156  Block *blk = reinterpret_cast<Block*>(reinterpret_cast<pUChar>(data) - sizeof(Block));
157  blk->next(free_);
158  free_ = blk;
159  }
160 
161  private:
162  Void setSize()
163  {
164  if (as_ == 0)
165  return;
166 
167  if (ns_ == 0)
168  {
169  bs_ = sizeof(Block) + as_;
170  bs_ += bs_ % sizeof(pVoid);
171  if (bc_ == 0)
172  bc_ = 1;
173  ns_ = sizeof(Node) + bs_ * bc_;
174  }
175  else
176  {
177  bs_ = sizeof(Block) + as_;
178  bs_ += bs_ % sizeof(pVoid);
179  bc_ = (ns_ - sizeof(Node)) / bs_;
180  if (bc_ == 0)
181  throw EMemory_NodeSizeTooSmall();
182  }
183  }
184 
185  EMutexPrivate mutex_;
186  Node *head_;
187  Block *free_;
188  size_t as_;
189  size_t ns_;
190  size_t bs_;
191  size_t bc_;
192  };
193 };
194 
195 #endif // #ifndef __EMEMORY_H
size_t nodeSize() const
Definition: ememory.h:118
pUChar data()
Definition: ememory.h:47
static ETime Now()
Retrieves the current time.
Definition: etime.cpp:1147
Definition: ememory.h:29
Pool & pool()
Definition: ememory.h:78
Pool & setSize(size_t as, size_t ns, size_t bc=0)
Definition: ememory.h:120
Block * next()
Definition: ememory.h:46
Definition: ememory.h:72
Block & next(Block *nxt)
Definition: ememory.h:61
Node * next()
Definition: ememory.h:79
Definition: ememory.h:34
Provides class for manipulating time of day values.
size_t allocSize() const
Definition: ememory.h:115
Class for manipulating date and time of day values.
Definition: etime.h:199
size_t blockSize() const
Definition: ememory.h:116
Block()
Definition: ememory.h:38
Defines base class for exceptions and declaration helper macros.
DECLARE_ERROR(EMemory_NodeSizeTooSmall)
Definition: ememory.h:92
size_t blockCount() const
Definition: ememory.h:117
Node & next(Node *nxt)
Definition: ememory.h:83
Acquires and holds a lock on the specified mutex.
Definition: esynch.h:133
Pool(size_t allocSize=0, size_t nodeSize=0, size_t blockCount=0)
Definition: ememory.h:95
A private mutex (the mutex data is allocated from either the heap or stack).
Definition: esynch.h:175
Void deallocate(pVoid data)
Definition: ememory.h:153
Node(Pool &pool)
Definition: ememory.h:76
~Pool()
Definition: ememory.h:105
Contains definitions for synchronization objects.
pVoid allocate()
Definition: ememory.h:129
pUChar data()
Definition: ememory.h:80