ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
ObjectPool.h
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
14#ifndef ETISS_OBJECTPOOL_H_
15#define ETISS_OBJECTPOOL_H_
16
17#include "etiss/Misc.h"
19
20#include <cstring>
21
22#define ETISS_OBJECTPOOL_LOGSIZE 1
23#define ETISS_OBJECTPOOL_DBG_OBJLIMIT 0 // set to 0 to disable
24
25namespace etiss
26{
27
28template <typename T, size_t prealloc_inc = 100>
29class ObjectPool;
30
31namespace internal
32{
33// functions to set a pointer from object to memory pool if object inherited
34// RefCounted Object
35template <typename T>
37typename std::enable_if<!std::is_base_of<etiss::RefCountedObject<ObjectPool<T>>, T>::value, void>::type
41template <typename T>
42typename std::enable_if<std::is_base_of<etiss::RefCountedObject<ObjectPool<T>>, T>::value, void>::type
44{
45 etiss::helper_allocator_ptr_ref<T, ObjectPool<T>>(obj) = this_;
46}
47} // namespace internal
48
49// patch missing alignof support for msvc
50#ifdef _MSC_VER
51#define alignof(x) __alignof(x)
52#endif
54template <typename T, size_t prealloc_inc>
60{
61 public:
62 const size_t blocksize_;
63
64 private:
65 std::set<void *> areas_;
66 std::vector<void *> empty_;
67
68 public:
69 typedef T value_type;
70 typedef T *pointer;
71 typedef const T *const_pointer;
72 typedef T &reference;
73 typedef const T &const_reference;
74
75 typedef typename std::aligned_storage<sizeof(T), alignof(T)>::type storage;
76
77 private:
78 storage stackstore[prealloc_inc]; // small (fast) possibly stack allocation of the first elements
80
81 public:
82 template <class Type>
83 struct rebind
84 {
86 };
87
88 ObjectPool(size_t blockElementCount = 5000) : blocksize_(blockElementCount), stackstore_used(false) {}
90 template <class U>
95 {
96 // no other cleanup must be preformed since all allocated objects are required to be destroyed prior to this
97 // destruction
98 for (auto iter = areas_.begin(); iter != areas_.end(); ++iter)
99 if (*iter != stackstore)
100 delete[] (storage *)(*iter);
101 }
102
103 T *address(T &x) const { return &x; }
104 const T *address(const T &x) const { return &x; }
105 T *allocate(size_t n = 1, const T * = 0)
106 {
107 if (unlikely(n <= 0))
108 throw std::bad_alloc();
109 if (unlikely(n > 1)) // fall back to simple malloc call
110 {
111 return (T *)new storage[n];
112 }
113 else
114 {
115 if (unlikely(empty_.empty()))
116 {
117 if (!stackstore_used)
118 {
119 stackstore_used = true;
120 for (size_t i = 0; i < prealloc_inc; ++i)
121 {
122 empty_.push_back((void *)(&(stackstore[i])));
123 }
124 }
125 else
126 {
127 storage *area = new storage[blocksize_];
128 if (area == 0)
129 throw std::bad_alloc();
130 areas_.insert(area);
131#if ETISS_OBJECTPOOL_DBG_OBJLIMIT
133 throw new std::bad_alloc();
134#endif
135 for (size_t i = 0; i < blocksize_; ++i)
136 {
137 empty_.push_back((void *)(&(area[i])));
138 }
139#if ETISS_OBJECTPOOL_LOGSIZE
140 // etiss::log(etiss::VERBOSE,"ObjectPool increased size",areas_.size()*blocksize_+100);
141#endif
142 }
143 }
144 void *area = empty_.back();
145 empty_.pop_back();
146 return (T *)area;
147 }
148 }
149 void deallocate(T *p, size_t n = 1)
150 {
151 if (unlikely(p == 0))
152 return;
153 if (unlikely(n <= 0))
154 throw std::bad_alloc();
155 if (unlikely(n > 1))
156 {
157 delete[] (storage *)p;
158 }
159 else
160 {
161 empty_.push_back(p);
162 }
163 }
164 size_t max_size() const { return (size_t)-1; }
165 template <class U, class... Args>
166 void construct(U *p, Args &&...args)
167 {
168 ::new ((void *)p) U(std::forward<Args>(args)...);
169 etiss::internal::ObjectPool_setAllocatorPointer<T>((T *)p, this);
170 }
171 template <class U>
172 void destroy(U *p)
173 {
174 p->~U();
175 }
176};
177
178template <typename T>
179typename std::enable_if<std::is_base_of<etiss::RefCountedObject<ObjectPool<T>>, T>::value, bool>::type decRef(T *ptr)
180{
181 bool ret = helper_decRef<T, typename T::refcount_allocatorT>(ptr);
182 if (ret)
183 {
184 ObjectPool<T> *&pool = etiss::helper_allocator_ptr_ref<T, typename T::refcount_allocatorT>(ptr);
185#if DEBUG
186 if (pool == 0)
187 throw std::bad_alloc();
188#endif
189 pool->destroy(ptr);
190 pool->deallocate(ptr);
191 ptr = 0;
192 }
193 return ret;
194}
195
202template <typename T, size_t stackallocatedsize = 1>
204{
205 static_assert(std::is_pod<T>::value, "ExpandingNativeStack can only handle types without constructor/destructor. "
206 "This cannot be fullfilled by non POD objects");
207
208 private:
209 T stackbuf_[stackallocatedsize > 0 ? stackallocatedsize : 1]; // must be >0 to conform to c++ standard
211 size_t size_;
212 ssize_t pos_;
213
214 public:
215 ExpandingNativeStack() : stack_(stackbuf_), size_(stackallocatedsize > 0 ? stackallocatedsize : 1), pos_(-1) {}
217 {
218 if (stack_ != stackbuf_)
219 delete stack_;
220 }
221 inline T operator[](ssize_t pos)
222 {
223#if DEBUG
224 if (unlikely((pos >= size_) || pos < 0))
225 etiss::log(etiss::FATALERROR, "Array index out of bounds", pos, ETISS_SRCLOC);
226#endif
227 return stack_[pos];
228 }
229 inline const T operator[](size_t pos) const
230 {
231#if DEBUG
232 if (unlikely((pos >= size_) || pos < 0))
233 etiss::log(etiss::FATALERROR, "Array index out of bounds", pos, ETISS_SRCLOC);
234#endif
235 return stack_[pos];
236 }
237 inline ssize_t pos() const { return pos_; }
238 inline ssize_t size() const { return pos_ + 1; }
239 inline ssize_t capacity() const { return size_; }
240 inline T &back() { return stack_[pos_]; }
241 inline const T &back() const { return stack_[pos_]; }
242 inline T &front() { return stack_[0]; }
243 inline const T &front() const { return stack_[0]; }
244 inline void pop()
245 {
246#if DEBUG
247 if (unlikely(pos_ < 0))
248 etiss::log(etiss::FATALERROR, "Array index out of bounds (negative)", ETISS_SRCLOC);
249#endif
250 --pos_;
251 }
252 inline void push(T t)
253 {
254 if (unlikely((++pos_) == (ssize_t)size_)) // reached end of old stack
255 {
256 size_t new_size = size_ + 10 + (size_ / 20); // increase stack size
257 T *tmp = new T[new_size]; // allocate new stack
258 memcpy(tmp, stack_, size_ * sizeof(T)); // copy old elements
259 if (stack_ != stackbuf_)
260 delete[] stack_;
261 stack_ = tmp;
262 size_ = new_size;
263 }
264 stack_[pos_] = t;
265 }
266 inline bool empty() const { return pos_ < 0; }
267};
268
269} // namespace etiss
270
271#endif
general configuration and logging
#define ETISS_SRCLOC
Definition Misc.h:202
#define ETISS_OBJECTPOOL_DBG_OBJLIMIT
Definition ObjectPool.h:23
__DEVICE__ void * memcpy(void *__a, const void *__b, size_t __c)
#define unlikely(x)
Definition types.h:36
implements a stack that may only grow (if needed) and can only contain native types since no destruct...
Definition ObjectPool.h:204
const T operator[](size_t pos) const
Definition ObjectPool.h:229
T stackbuf_[stackallocatedsize > 0 ? stackallocatedsize :1]
Definition ObjectPool.h:209
const T & front() const
Definition ObjectPool.h:243
const T & back() const
Definition ObjectPool.h:241
prealloc_inc defines the number of objects that is availabe within ObjectPools memory; default: 100
Definition ObjectPool.h:60
void construct(U *p, Args &&...args)
Definition ObjectPool.h:166
const T & const_reference
Definition ObjectPool.h:73
T * address(T &x) const
Definition ObjectPool.h:103
std::set< void * > areas_
Definition ObjectPool.h:65
ObjectPool(size_t blockElementCount=5000)
Definition ObjectPool.h:88
ObjectPool(const ObjectPool &alloc)
Definition ObjectPool.h:89
const T * const_pointer
Definition ObjectPool.h:71
std::aligned_storage< sizeof(T), alignof(T)>::type storage
Definition ObjectPool.h:75
storage stackstore[prealloc_inc]
Definition ObjectPool.h:78
ObjectPool(const ObjectPool< U > &alloc)
Definition ObjectPool.h:91
size_t max_size() const
Definition ObjectPool.h:164
void destroy(U *p)
Definition ObjectPool.h:172
T * allocate(size_t n=1, const T *=0)
Definition ObjectPool.h:105
const T * address(const T &x) const
Definition ObjectPool.h:104
void deallocate(T *p, size_t n=1)
Definition ObjectPool.h:149
std::vector< void * > empty_
Definition ObjectPool.h:66
const size_t blocksize_
Definition ObjectPool.h:62
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:38
forwards: include/jit/*
Definition Benchmark.h:17
std::enable_if< std::is_base_of< etiss::RefCountedObject< ObjectPool< T > >, T >::value, bool >::type decRef(T *ptr)
Definition ObjectPool.h:179
@ FATALERROR
Definition Misc.h:84
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
#define false
Definition stdbool.h:17
ObjectPool< Type > other
Definition ObjectPool.h:85