ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
ObjectPool.h
Go to the documentation of this file.
1 
52 #ifndef ETISS_OBJECTPOOL_H_
53 #define ETISS_OBJECTPOOL_H_
54 
55 #include "etiss/Misc.h"
56 #include "etiss/RefCountedObject.h"
57 
58 #include <cstring>
59 
60 #define ETISS_OBJECTPOOL_LOGSIZE 1
61 #define ETISS_OBJECTPOOL_DBG_OBJLIMIT 0 // set to 0 to disable
62 
63 namespace etiss
64 {
65 
66 template <typename T, size_t prealloc_inc = 100>
67 class ObjectPool;
68 
69 namespace internal
70 {
71 // functions to set a pointer from object to memory pool if object inherited
72 // RefCounted Object
73 template <typename T>
75 typename std::enable_if<!std::is_base_of<etiss::RefCountedObject<ObjectPool<T>>, T>::value, void>::type
77 {
78 }
79 template <typename T>
80 typename std::enable_if<std::is_base_of<etiss::RefCountedObject<ObjectPool<T>>, T>::value, void>::type
82 {
83  etiss::helper_allocator_ptr_ref<T, ObjectPool<T>>(obj) = this_;
84 }
85 } // namespace internal
86 
87 // patch missing alignof support for msvc
88 #ifdef _MSC_VER
89 #define alignof(x) __alignof(x)
90 #endif
92 template <typename T, size_t prealloc_inc>
98 {
99  public:
100  const size_t blocksize_;
101 
102  private:
103  std::set<void *> areas_;
104  std::vector<void *> empty_;
105 
106  public:
107  typedef T value_type;
108  typedef T *pointer;
109  typedef const T *const_pointer;
110  typedef T &reference;
111  typedef const T &const_reference;
112 
113  typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
114 
115  private:
116  storage stackstore[prealloc_inc]; // small (fast) possibly stack allocation of the first elements
118 
119  public:
120  template <class Type>
121  struct rebind
122  {
124  };
125 
126  ObjectPool(size_t blockElementCount = 5000) : blocksize_(blockElementCount), stackstore_used(false) {}
128  template <class U>
130  {
131  }
133  {
134  // no other cleanup must be preformed since all allocated objects are required to be destroyed prior to this
135  // destruction
136  for (auto iter = areas_.begin(); iter != areas_.end(); ++iter)
137  if (*iter != stackstore)
138  delete[](storage *)(*iter);
139  }
140 
141  T *address(T &x) const { return &x; }
142  const T *address(const T &x) const { return &x; }
143  T *allocate(size_t n = 1, const T * = 0)
144  {
145  if (unlikely(n <= 0))
146  throw std::bad_alloc();
147  if (unlikely(n > 1)) // fall back to simple malloc call
148  {
149  return (T *)new storage[n];
150  }
151  else
152  {
153  if (unlikely(empty_.empty()))
154  {
155  if (!stackstore_used)
156  {
157  stackstore_used = true;
158  for (size_t i = 0; i < prealloc_inc; ++i)
159  {
160  empty_.push_back((void *)(&(stackstore[i])));
161  }
162  }
163  else
164  {
165  storage *area = new storage[blocksize_];
166  if (area == 0)
167  throw std::bad_alloc();
168  areas_.insert(area);
169 #if ETISS_OBJECTPOOL_DBG_OBJLIMIT
171  throw new std::bad_alloc();
172 #endif
173  for (size_t i = 0; i < blocksize_; ++i)
174  {
175  empty_.push_back((void *)(&(area[i])));
176  }
177 #if ETISS_OBJECTPOOL_LOGSIZE
178  // etiss::log(etiss::VERBOSE,"ObjectPool increased size",areas_.size()*blocksize_+100);
179 #endif
180  }
181  }
182  void *area = empty_.back();
183  empty_.pop_back();
184  return (T *)area;
185  }
186  }
187  void deallocate(T *p, size_t n = 1)
188  {
189  if (unlikely(p == 0))
190  return;
191  if (unlikely(n <= 0))
192  throw std::bad_alloc();
193  if (unlikely(n > 1))
194  {
195  delete[](storage *) p;
196  }
197  else
198  {
199  empty_.push_back(p);
200  }
201  }
202  size_t max_size() const { return (size_t)-1; }
203  template <class U, class... Args>
204  void construct(U *p, Args &&... args)
205  {
206  ::new ((void *)p) U(std::forward<Args>(args)...);
207  etiss::internal::ObjectPool_setAllocatorPointer<T>((T *)p, this);
208  }
209  template <class U>
210  void destroy(U *p)
211  {
212  p->~U();
213  }
214 };
215 
216 template <typename T>
217 typename std::enable_if<std::is_base_of<etiss::RefCountedObject<ObjectPool<T>>, T>::value, bool>::type decRef(T *ptr)
218 {
219  bool ret = helper_decRef<T, typename T::refcount_allocatorT>(ptr);
220  if (ret)
221  {
222  ObjectPool<T> *&pool = etiss::helper_allocator_ptr_ref<T, typename T::refcount_allocatorT>(ptr);
223 #if DEBUG
224  if (pool == 0)
225  throw std::bad_alloc();
226 #endif
227  pool->destroy(ptr);
228  pool->deallocate(ptr);
229  ptr = 0;
230  }
231  return ret;
232 }
233 
240 template <typename T, size_t stackallocatedsize = 1>
242 {
243  static_assert(std::is_pod<T>::value, "ExpandingNativeStack can only handle types without constructor/destructor. "
244  "This cannot be fullfilled by non POD objects");
245 
246  private:
247  T stackbuf_[stackallocatedsize > 0 ? stackallocatedsize : 1]; // must be >0 to conform to c++ standard
248  T *stack_;
249  size_t size_;
250  ssize_t pos_;
251 
252  public:
253  ExpandingNativeStack() : stack_(stackbuf_), size_(stackallocatedsize > 0 ? stackallocatedsize : 1), pos_(-1) {}
255  {
256  if (stack_ != stackbuf_)
257  delete stack_;
258  }
259  inline T operator[](ssize_t pos)
260  {
261 #if DEBUG
262  if (unlikely((pos >= size_) || pos < 0))
263  etiss::log(etiss::FATALERROR, "Array index out of bounds", pos, ETISS_SRCLOC);
264 #endif
265  return stack_[pos];
266  }
267  inline const T operator[](size_t pos) const
268  {
269 #if DEBUG
270  if (unlikely((pos >= size_) || pos < 0))
271  etiss::log(etiss::FATALERROR, "Array index out of bounds", pos, ETISS_SRCLOC);
272 #endif
273  return stack_[pos];
274  }
275  inline ssize_t pos() const { return pos_; }
276  inline ssize_t size() const { return pos_ + 1; }
277  inline ssize_t capacity() const { return size_; }
278  inline T &back() { return stack_[pos_]; }
279  inline const T &back() const { return stack_[pos_]; }
280  inline T &front() { return stack_[0]; }
281  inline const T &front() const { return stack_[0]; }
282  inline void pop()
283  {
284 #if DEBUG
285  if (unlikely(pos_ < 0))
286  etiss::log(etiss::FATALERROR, "Array index out of bounds (negative)", ETISS_SRCLOC);
287 #endif
288  --pos_;
289  }
290  inline void push(T t)
291  {
292  if (unlikely((++pos_) == (ssize_t)size_)) // reached end of old stack
293  {
294  size_t new_size = size_ + 10 + (size_ / 20); // increase stack size
295  T *tmp = new T[new_size]; // allocate new stack
296  memcpy(tmp, stack_, size_ * sizeof(T)); // copy old elements
297  if (stack_ != stackbuf_)
298  delete[] stack_;
299  stack_ = tmp;
300  size_ = new_size;
301  }
302  stack_[pos_] = t;
303  }
304  inline bool empty() const { return pos_ < 0; }
305 };
306 
307 } // namespace etiss
308 
309 #endif
#define static_assert(x, y)
Definition: Fault.cpp:60
general configuration and logging
#define ETISS_SRCLOC
Definition: Misc.h:239
#define ETISS_OBJECTPOOL_DBG_OBJLIMIT
Definition: ObjectPool.h:61
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
#define unlikely(x)
Definition: types.h:74
implements a stack that may only grow (if needed) and can only contain native types since no destruct...
Definition: ObjectPool.h:242
const T operator[](size_t pos) const
Definition: ObjectPool.h:267
const T & front() const
Definition: ObjectPool.h:281
T stackbuf_[stackallocatedsize > 0 ? stackallocatedsize :1]
Definition: ObjectPool.h:244
T operator[](ssize_t pos)
Definition: ObjectPool.h:259
ssize_t capacity() const
Definition: ObjectPool.h:277
const T & back() const
Definition: ObjectPool.h:279
prealloc_inc defines the number of objects that is availabe within ObjectPools memory; default: 100
Definition: ObjectPool.h:98
const T & const_reference
Definition: ObjectPool.h:111
std::set< void * > areas_
Definition: ObjectPool.h:103
ObjectPool(size_t blockElementCount=5000)
Definition: ObjectPool.h:126
T * address(T &x) const
Definition: ObjectPool.h:141
ObjectPool(const ObjectPool &alloc)
Definition: ObjectPool.h:127
const T * const_pointer
Definition: ObjectPool.h:109
storage stackstore[prealloc_inc]
Definition: ObjectPool.h:116
ObjectPool(const ObjectPool< U > &alloc)
Definition: ObjectPool.h:129
size_t max_size() const
Definition: ObjectPool.h:202
void construct(U *p, Args &&... args)
Definition: ObjectPool.h:204
void destroy(U *p)
Definition: ObjectPool.h:210
const T * address(const T &x) const
Definition: ObjectPool.h:142
void deallocate(T *p, size_t n=1)
Definition: ObjectPool.h:187
T * allocate(size_t n=1, const T *=0)
Definition: ObjectPool.h:143
std::vector< void * > empty_
Definition: ObjectPool.h:104
const size_t blocksize_
Definition: ObjectPool.h:100
std::aligned_storage< sizeof(T), alignof(T)>::type storage
Definition: ObjectPool.h:113
std::enable_if<!std::is_base_of< etiss::RefCountedObject< ObjectPool< T > >, T >::value, void >::type ObjectPool_setAllocatorPointer(T *obj, ObjectPool< T > *this_)
empty fallback function
Definition: ObjectPool.h:76
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition: Benchmark.h:53
std::enable_if< std::is_base_of< etiss::RefCountedObject< ObjectPool< T > >, T >::value, bool >::type decRef(T *ptr)
Definition: ObjectPool.h:217
@ FATALERROR
Definition: Misc.h:126
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition: Misc.cpp:125
#define false
Definition: stdbool.h:17
ObjectPool< Type > other
Definition: ObjectPool.h:123