Nvwa  1.1
fixed_mem_pool.h
Go to the documentation of this file.
1 // -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
2 // vim:tabstop=4:shiftwidth=4:expandtab:
3 
4 /*
5  * Copyright (C) 2005-2014 Wu Yongwei <adah at users dot sourceforge dot net>
6  *
7  * This software is provided 'as-is', without any express or implied
8  * warranty. In no event will the authors be held liable for any
9  * damages arising from the use of this software.
10  *
11  * Permission is granted to anyone to use this software for any purpose,
12  * including commercial applications, and to alter it and redistribute
13  * it freely, subject to the following restrictions:
14  *
15  * 1. The origin of this software must not be misrepresented; you must
16  * not claim that you wrote the original software. If you use this
17  * software in a product, an acknowledgement in the product
18  * documentation would be appreciated but is not required.
19  * 2. Altered source versions must be plainly marked as such, and must
20  * not be misrepresented as being the original software.
21  * 3. This notice may not be removed or altered from any source
22  * distribution.
23  *
24  * This file is part of Stones of Nvwa:
25  * http://sourceforge.net/projects/nvwa
26  *
27  */
28 
55 #ifndef NVWA_FIXED_MEM_POOL_H
56 #define NVWA_FIXED_MEM_POOL_H
57 
58 #include <new> // std::bad_alloc
59 #include <assert.h> // assert
60 #include <stddef.h> // size_t/NULL
61 #include "_nvwa.h" // NVWA/NVWA_NAMESPACE_*
62 #include "c++11.h" // _NOEXCEPT
63 #include "class_level_lock.h" // nvwa::class_level_lock
64 #include "mem_pool_base.h" // nvwa::mem_pool_base
65 #include "static_assert.h" // STATIC_ASSERT
66 
67 NVWA_NAMESPACE_BEGIN
68 
72 #ifndef MEM_POOL_ALIGNMENT
73 #define MEM_POOL_ALIGNMENT sizeof(void*)
74 #endif
75 
82 template <class _Tp>
84 {
85 public:
91  struct alignment
92  {
93  static const size_t value = MEM_POOL_ALIGNMENT;
94  };
99  struct block_size
100  {
101  static const size_t value =
102  (sizeof(_Tp) + fixed_mem_pool<_Tp>::alignment::value - 1)
104  };
105  static void* allocate();
106  static void deallocate(void*);
107  static bool initialize(size_t size);
108  static int deinitialize();
109  static int get_alloc_count();
110  static bool is_initialized();
111 protected:
112  static bool bad_alloc_handler();
113 private:
114  static void* _S_mem_pool_ptr;
115  static void* _S_first_avail_ptr;
116  static int _S_alloc_cnt;
117 };
118 
120 template <class _Tp>
121 void* fixed_mem_pool<_Tp>::_S_mem_pool_ptr = _NULLPTR;
122 
124 template <class _Tp>
126 
128 template <class _Tp>
130 
136 template <class _Tp>
138 {
139  lock guard;
140  for (;;)
141  {
142  if (void* result = _S_first_avail_ptr)
143  {
144  _S_first_avail_ptr = *(void**)_S_first_avail_ptr;
145  ++_S_alloc_cnt;
146  return result;
147  }
148  else
149  if (!bad_alloc_handler())
150  return _NULLPTR;
151  }
152 }
153 
159 template <class _Tp>
160 inline void fixed_mem_pool<_Tp>::deallocate(void* block_ptr)
161 {
162  if (block_ptr == _NULLPTR)
163  return;
164  lock guard;
165  assert(_S_alloc_cnt != 0);
166  --_S_alloc_cnt;
167  *(void**)block_ptr = _S_first_avail_ptr;
168  _S_first_avail_ptr = block_ptr;
169 }
170 
177 template <class _Tp>
179 {
180  STATIC_ASSERT(alignment::value > 0 && alignment::value <= 8192,
181  Bad_alignment);
182  STATIC_ASSERT((alignment::value & (alignment::value - 1)) == 0,
183  Alignment_must_be_power_of_two);
184  STATIC_ASSERT(block_size::value >= sizeof(void*),
185  Alignment_too_small);
186  assert(!is_initialized());
187  assert(size > 0);
188  _S_mem_pool_ptr = mem_pool_base::alloc_sys(size * block_size::value);
189  _S_first_avail_ptr = _S_mem_pool_ptr;
190  if (_S_mem_pool_ptr == _NULLPTR)
191  return false;
192  char* block = (char*)_S_mem_pool_ptr;
193  while (--size != 0)
194  {
195  char* next = block + block_size::value;
196  *(void**)block = next;
197  block = next;
198  }
199  *(void**)block = _NULLPTR;
200  return true;
201 }
202 
210 template <class _Tp>
212 {
213  if (_S_alloc_cnt != 0)
214  return _S_alloc_cnt;
215  assert(is_initialized());
216  mem_pool_base::dealloc_sys(_S_mem_pool_ptr);
217  _S_mem_pool_ptr = _NULLPTR;
218  _S_first_avail_ptr = _NULLPTR;
219  return 0;
220 }
221 
227 template <class _Tp>
229 {
230  return _S_alloc_cnt;
231 }
232 
238 template <class _Tp>
240 {
241  return _S_mem_pool_ptr != _NULLPTR;
242 }
243 
252 template <class _Tp>
254 {
255  return false;
256 }
257 
258 NVWA_NAMESPACE_END
259 
269 #define DECLARE_FIXED_MEM_POOL(_Cls) \
270 public: \
271  static void* operator new(size_t size) \
272  { \
273  assert(size == sizeof(_Cls)); \
274  if (void* ptr = NVWA::fixed_mem_pool<_Cls>::allocate()) \
275  return ptr; \
276  else \
277  throw std::bad_alloc(); \
278  } \
279  static void operator delete(void* ptr) \
280  { \
281  if (ptr != _NULLPTR) \
282  NVWA::fixed_mem_pool<_Cls>::deallocate(ptr); \
283  }
284 
290 #define DECLARE_FIXED_MEM_POOL__NOTHROW(_Cls) \
291 public: \
292  static void* operator new(size_t size) _NOEXCEPT \
293  { \
294  assert(size == sizeof(_Cls)); \
295  return NVWA::fixed_mem_pool<_Cls>::allocate(); \
296  } \
297  static void operator delete(void* ptr) \
298  { \
299  if (ptr != _NULLPTR) \
300  NVWA::fixed_mem_pool<_Cls>::deallocate(ptr); \
301  }
302 
315 #define DECLARE_FIXED_MEM_POOL__THROW_NOCHECK(_Cls) \
316 public: \
317  static void* operator new(size_t size) \
318  { \
319  assert(size == sizeof(_Cls)); \
320  return NVWA::fixed_mem_pool<_Cls>::allocate(); \
321  } \
322  static void operator delete(void* ptr) \
323  { \
324  if (ptr != _NULLPTR) \
325  NVWA::fixed_mem_pool<_Cls>::deallocate(ptr); \
326  }
327 
328 #endif // NVWA_FIXED_MEM_POOL_H
Helper class for class-level locking.
Definition: class_level_lock.h:76
In essence Loki ClassLevelLockable re-engineered to use a fast_mutex class.
Specializable struct to define the alignment of an object in the fixed_mem_pool.
Definition: fixed_mem_pool.h:91
static void * _S_mem_pool_ptr
Pointer to the allocated chunk of memory.
Definition: fixed_mem_pool.h:114
Type that provides locking/unlocking semantics.
Definition: class_level_lock.h:89
static int _S_alloc_cnt
Count of allocations.
Definition: fixed_mem_pool.h:116
Struct to calculate the block size based on the (specializable) alignment value.
Definition: fixed_mem_pool.h:99
C++11 feature detection macros and workarounds.
#define MEM_POOL_ALIGNMENT
Defines the alignment of memory blocks.
Definition: fixed_mem_pool.h:73
Header file for the memory pool base.
Class template to manipulate a fixed-size memory pool.
Definition: fixed_mem_pool.h:83
static void * _S_first_avail_ptr
Pointer to the first available memory block.
Definition: fixed_mem_pool.h:115
Common definitions for preprocessing.