QuantumLibrary
quantum_contiguous_pool_manager_impl.h
1 /*
2 ** Copyright 2018 Bloomberg Finance L.P.
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 //NOTE: DO NOT INCLUDE DIRECTLY
17 #include <type_traits>
18 #include <assert.h>
19 #include <exception>
20 
21 //##############################################################################################
22 //#################################### IMPLEMENTATIONS #########################################
23 //##############################################################################################
24 namespace Bloomberg {
25 namespace quantum {
26 
27 template <typename T>
29 {
30 }
31 
32 template <typename T>
34 {
35  setBuffer(buffer, size);
36 }
37 
38 template <typename T>
40 {
41  *this = std::move(other);
42 }
43 
44 template <typename T>
46 {
47  _size = other._size;
48  _buffer = other.buffer;
49  _freeBlocks = other._freeBlocks;
50  _freeBlockIndex = other._freeBlockIndex;
51  _numHeapAllocatedBlocks = other._numHeapAllocatedBlocks;
52  _spinlock = std::move(other._spinlock);
53 
54  // Reset other
55  other._buffer = nullptr;
56  other._freeBlocks = nullptr;
57  other._freeBlockIndex = -1;
58  other._numHeapAllocatedBlocks = 0;
59 }
60 
61 template <typename T>
63 {
64  delete[] _freeBlocks;
65 }
66 
67 template <typename T>
69 {
70  if (!buffer) {
71  throw std::runtime_error("Null buffer");
72  }
73  if (size == 0) {
74  throw std::runtime_error("Invalid allocator pool size");
75  }
76  _size = size;
77  _buffer = buffer;
78  _freeBlocks = new index_type[size];
79  if (!_freeBlocks) {
80  throw std::bad_alloc();
81  }
82  _freeBlockIndex = size-1;
83  //build the free stack
84  for (index_type i = 0; i < size; ++i) {
85  _freeBlocks[i] = i;
86  }
87 }
88 
89 template <typename T>
91 {
92  return &x;
93 }
94 
95 template <typename T>
97 {
98  return &x;
99 }
100 
101 template <typename T>
103 {
104  return 1; //only 1 supported for now
105 }
106 
107 template <typename T>
108 template <typename... Args >
109 void ContiguousPoolManager<T>::construct(T* p, Args&&... args)
110 {
111  new((void *)p) T(std::forward<Args>(args)...); // construct in-place
112 }
113 
114 template <typename T>
116 {
117  if (p != nullptr)
118  {
119  p->~T();
120  }
121 }
122 
123 template <typename T>
126 {
127  assert(_buffer);
128  {
129  SpinLock::Guard lock(_spinlock);
130  if (findContiguous(static_cast<index_type>(n)))
131  {
132  _freeBlockIndex -= (n - 1);
133  return reinterpret_cast<pointer>(&_buffer[_freeBlocks[_freeBlockIndex--]]);
134  }
135  // Use heap allocation
136  ++_numHeapAllocatedBlocks;
137  }
138  return (pointer)new char[sizeof(value_type)];
139 }
140 
141 template <typename T>
143 {
144  assert(_buffer);
145  if (p == nullptr) {
146  return;
147  }
148  if (isManaged(p)) {
149  //find index of the block and return the individual blocks to the free pool
150  SpinLock::Guard lock(_spinlock);
151  for (size_type i = 0; i < n; ++i) {
152  _freeBlocks[++_freeBlockIndex] = blockIndex(p+i);
153  }
154  }
155  else {
156  delete[] (char*)p;
157  SpinLock::Guard lock(_spinlock);
158  --_numHeapAllocatedBlocks;
159  assert(_numHeapAllocatedBlocks >= 0);
160  }
161 }
162 
163 template <typename T>
164 template <typename... Args >
166 {
167  T* p = allocate();
168  construct(p, std::forward<Args>(args)...);
169  return p;
170 }
171 
172 template <typename T>
174 {
175  destroy(p);
176  deallocate(p);
177 }
178 
179 template <typename T>
181 {
182  return _size ? _size - _freeBlockIndex - 1 : 0;
183 }
184 
185 template <typename T>
187 {
188  return _numHeapAllocatedBlocks;
189 }
190 
191 template <typename T>
193 {
194  return _freeBlockIndex == _size-1;
195 }
196 
197 template <typename T>
199 {
200  return _freeBlockIndex == -1;
201 }
202 
203 template <typename T>
205 {
206  return reinterpret_cast<pointer>(_buffer);
207 }
208 
209 template <typename T>
210 typename ContiguousPoolManager<T>::pointer ContiguousPoolManager<T>::bufferEnd()
211 {
212  return reinterpret_cast<pointer>(_buffer + _size);
213 }
214 
215 template <typename T>
216 bool ContiguousPoolManager<T>::isManaged(pointer p)
217 {
218  return (bufferStart() <= p) && (p < bufferEnd());
219 }
220 
221 template <typename T>
222 typename ContiguousPoolManager<T>::index_type ContiguousPoolManager<T>::blockIndex(pointer p)
223 {
224  return static_cast<index_type>(reinterpret_cast<aligned_type*>(p) - _buffer);
225 }
226 
227 template <typename T>
228 bool ContiguousPoolManager<T>::findContiguous(index_type n)
229 {
230  if ((_freeBlockIndex + 1) < n) {
231  return false;
232  }
233  bool found = true;
234  aligned_type* last = &_buffer[_freeBlocks[_freeBlockIndex]];
235  for (ssize_t i = _freeBlockIndex-1; i > _freeBlockIndex-n; --i) {
236  aligned_type* first = &_buffer[_freeBlocks[i]];
237  if ((last-first) != (_freeBlockIndex-i)) {
238  return false;
239  }
240  }
241  return found;
242 }
243 
244 }}
245 
virtual ~ContiguousPoolManager()
Definition: quantum_contiguous_pool_manager_impl.h:62
const value_type * const_pointer
Definition: quantum_contiguous_pool_manager.h:46
uint16_t index_type
Definition: quantum_contiguous_pool_manager.h:50
Definition: quantum_spinlock.h:71
Provides fast (quasi zero-time) in-place allocation for STL containers. Objects are allocated from a ...
Definition: quantum_contiguous_pool_manager.h:40
Definition: quantum_buffer_impl.h:22
size_t allocatedBlocks() const
Definition: quantum_contiguous_pool_manager_impl.h:180
bool isFull() const
Definition: quantum_contiguous_pool_manager_impl.h:192
size_t allocatedHeapBlocks() const
Definition: quantum_contiguous_pool_manager_impl.h:186
void dispose(pointer p)
Definition: quantum_contiguous_pool_manager_impl.h:173
ContiguousPoolManager & operator=(const this_type &)=delete
value_type & reference
Definition: quantum_contiguous_pool_manager.h:47
value_type * pointer
Definition: quantum_contiguous_pool_manager.h:45
void construct(T *p, Args &&... args)
Definition: quantum_contiguous_pool_manager_impl.h:109
T value_type
Definition: quantum_contiguous_pool_manager.h:44
const value_type & const_reference
Definition: quantum_contiguous_pool_manager.h:48
void deallocate(pointer p, size_type=1)
Definition: quantum_contiguous_pool_manager_impl.h:142
void setBuffer(aligned_type *buffer, index_type size)
Definition: quantum_contiguous_pool_manager_impl.h:68
bool isEmpty() const
Definition: quantum_contiguous_pool_manager_impl.h:198
pointer create(Args &&... args)
Definition: quantum_contiguous_pool_manager_impl.h:165
pointer allocate(size_type=1, const_pointer=0)
Definition: quantum_contiguous_pool_manager_impl.h:125
size_type max_size() const
Definition: quantum_contiguous_pool_manager_impl.h:102
pointer address(reference x) const
Definition: quantum_contiguous_pool_manager_impl.h:90
ContiguousPoolManager()
Definition: quantum_contiguous_pool_manager_impl.h:28
storage_type::type aligned_type
Definition: quantum_contiguous_pool_manager.h:52
void destroy(pointer p)
Definition: quantum_contiguous_pool_manager_impl.h:115
size_t size_type
Definition: quantum_contiguous_pool_manager.h:49