18 #ifndef LIBCWD_PRIVATE_ALLOCATOR_H
19 #define LIBCWD_PRIVATE_ALLOCATOR_H
21 #ifndef LIBCWD_CONFIG_H
25 #if CWDEBUG_ALLOC // This file is not used when --disable-alloc was used.
27 #ifndef LIBCWD_PRIVATE_MUTEX_INSTANCES_H
30 #ifndef LIBCWD_CORE_DUMP_H
37 #if __GNUC__ > 3 && LIBCWD_THREAD_SAFE
89 #if __GNUC__ == 3 && __GNUC_MINOR__ == 4
90 #include <ext/pool_allocator.h>
97 int const random_salt = 327665;
100 int const multi_threaded_internal_instance = -1;
101 int const single_threaded_internal_instance = -2;
102 int const userspace_instance = -3;
105 #if __GNUC__ == 3 && __GNUC_MINOR__ < 4
106 template<
bool needs_lock,
int pool_instance>
107 struct CharPoolAlloc :
public std::__default_alloc_template<needs_lock, random_salt + pool_instance> {
108 typedef char* pointer;
110 #elif __GNUC__ == 3 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 0
111 template<
bool needs_lock,
int pool_instance>
112 struct CharPoolAlloc :
public __gnu_cxx::__pool_alloc<needs_lock, random_salt + pool_instance> {
113 typedef char* pointer;
117 template<
int pool_instance>
118 struct char_wrapper {
122 template<
bool needs_lock,
int pool_instance>
123 class CharPoolAlloc :
public __gnu_cxx::__pool_alloc<char_wrapper<pool_instance> > { };
124 #else // gcc 4.0 and higher.
127 static size_t const maximum_size_exp = 10;
130 static size_t const maximum_size = (1U << maximum_size_exp);
136 Node* next(
void)
const {
return M_next; }
137 Node* prev(
void)
const {
return M_prev; }
141 M_prev->M_next = M_next;
142 M_next->M_prev = M_prev;
147 template <
unsigned int N>
struct log2 {
enum { result = 1 + log2<N/2>::result }; };
148 template<>
struct log2<0> {
enum { result = -1 }; };
149 static size_t const minimum_size_exp = log2<
sizeof(Node) - 1>::result + 1;
151 static size_t const minimum_size = (1U << minimum_size_exp);
153 static int const bucket_sizes = maximum_size_exp - minimum_size_exp + 1;
155 struct List :
public Node {
156 bool empty(
void)
const {
return M_next ==
this; }
157 void insert(Node* node)
160 node->M_next = M_next;
161 M_next->M_prev = node;
164 void insert_back(Node* node)
166 node->M_prev = M_prev;
168 M_prev->M_next = node;
176 struct ChunkNode :
public Node {
180 ChunkNode* next(
void)
const {
return static_cast<ChunkNode*
>(M_next); }
181 ChunkNode* prev(
void)
const {
return static_cast<ChunkNode*
>(M_prev); }
184 struct ChunkList :
public List {
185 unsigned int M_used_count;
186 ChunkNode* begin(
void)
const {
return static_cast<ChunkNode*
>(M_next); }
187 Node
const* end(
void)
const {
return this; }
190 struct BlockNode :
public Node {
194 BlockNode* next(
void)
const {
return static_cast<BlockNode*
>(M_next); }
195 BlockNode* prev(
void)
const {
return static_cast<BlockNode*
>(M_prev); }
198 struct BlockList :
public List {
199 unsigned int* M_count_ptr;
200 unsigned short M_internal;
202 BlockNode* begin(
void)
const {
return static_cast<BlockNode*
>(M_next); }
203 Node
const* end(
void)
const {
return this; }
205 void initialize(
unsigned int* count_ptr,
unsigned short internal);
206 void uninitialize(
void);
207 ~BlockList() { uninitialize(); }
209 void consistency_check(
void);
216 #if LIBCWD_THREAD_SAFE
217 pthread_mutex_t M_mutex;
218 static pthread_mutex_t S_mutex;
221 unsigned int M_count[bucket_sizes];
222 unsigned short M_keep[bucket_sizes];
223 BlockList M_list_notfull[bucket_sizes];
224 BlockList M_list_full[bucket_sizes];
226 #if LIBCWD_THREAD_SAFE
227 void initialize(TSD_st& __libcwd_tsd);
229 void initialize(
void);
231 void uninitialize(
void);
232 ~FreeList() { uninitialize(); }
233 char* allocate(
int power,
size_t size);
234 void deallocate(
char* p,
int power,
size_t size);
236 void consistency_check(
void);
240 template<
bool needs_lock,
int pool_instance>
241 class CharPoolAlloc {
243 static FreeList S_freelist;
247 typedef char value_type;
248 typedef size_t size_type;
249 typedef ptrdiff_t difference_type;
250 typedef char* pointer;
251 typedef char const* const_pointer;
252 typedef char& reference;
253 typedef char const& const_reference;
256 #if LIBCWD_THREAD_SAFE
257 pointer allocate(size_type num, TSD_st&);
259 pointer allocate(size_type num);
263 #if LIBCWD_THREAD_SAFE
264 void deallocate(pointer p, size_type num, TSD_st&);
266 void deallocate(pointer p, size_type num);
269 template <
bool needs_lock1,
int pool_instance1,
270 bool needs_lock2,
int pool_instance2>
272 bool operator==(CharPoolAlloc<needs_lock1, pool_instance1>
const&,
273 CharPoolAlloc<needs_lock2, pool_instance2>
const&);
274 template <
bool needs_lock1,
int pool_instance1,
275 bool needs_lock2,
int pool_instance2>
277 bool operator!=(CharPoolAlloc<needs_lock1, pool_instance1>
const&,
278 CharPoolAlloc<needs_lock2, pool_instance2>
const&);
280 size_type max_size(
void)
const {
return std::numeric_limits<size_type>::max(); }
282 #endif // gcc 4.0 and higher.
286 #define LIBCWD_COMMA_INT_INSTANCE , int instance
287 #define LIBCWD_COMMA_INSTANCE , instance
288 #define LIBCWD_DEBUGDEBUG_COMMA(x) , x
290 #define LIBCWD_COMMA_INT_INSTANCE
291 #define LIBCWD_COMMA_INSTANCE
292 #define LIBCWD_DEBUGDEBUG_COMMA(x)
305 template<
typename T,
class CharAlloc, pool_nt
internal LIBCWD_COMMA_INT_INSTANCE>
306 class allocator_adaptor {
309 CharAlloc M_char_allocator;
313 typedef T value_type;
314 typedef size_t size_type;
315 typedef ptrdiff_t difference_type;
317 typedef T
const* const_pointer;
318 typedef T& reference;
319 typedef T
const& const_reference;
324 typedef allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> other;
328 pointer address(reference value)
const {
return &value; }
329 const_pointer address(const_reference value)
const {
return &value; }
332 allocator_adaptor(
void) throw() { }
333 allocator_adaptor(allocator_adaptor
const& a) : M_char_allocator(a.M_char_allocator) { }
335 allocator_adaptor(allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE>
const& a) :
336 M_char_allocator(a.M_char_allocator) { }
337 template<
class T2,
class CharAlloc2, pool_nt
internal2 LIBCWD_DEBUGDEBUG_COMMA(
int instance2)>
338 friend class allocator_adaptor;
339 ~allocator_adaptor() throw() { }
342 size_type max_size(
void)
const {
return M_char_allocator.max_size() /
sizeof(T); }
345 pointer allocate(size_type num);
346 pointer allocate(size_type num,
void const* hint);
349 void deallocate(pointer p, size_type num);
352 void construct(pointer p, T
const& value) {
new ((
void*)p) T(value); }
355 void destroy(pointer p) { p->~T(); }
357 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGM
359 static void sanity_check(
void);
362 template <
class T1,
class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(
int inst1),
363 class T2,
class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(
int inst2)>
365 bool operator==(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)>
const& a1,
366 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)>
const& a2);
367 template <
class T1,
class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(
int inst1),
368 class T2,
class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(
int inst2)>
370 bool operator!=(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)>
const& a1,
371 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)>
const& a2);
374 #if LIBCWD_THREAD_SAFE
379 #define LIBCWD_CHARALLOCATOR_USERSPACE(instance) ::libcwd::_private_:: \
380 allocator_adaptor<char, \
381 CharPoolAlloc<true, userspace_instance>, \
383 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
392 #if LIBCWD_THREAD_SAFE
393 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) \
394 ::libcwd::_private_::instance == \
395 ::libcwd::_private_::multi_threaded_internal_instance || \
396 ::libcwd::_private_::instance == \
397 ::libcwd::_private_::memblk_map_instance
398 #else // !LIBCWD_THREAD_SAFE
399 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) false
400 #endif // !LIBCWD_THREAD_SAFE
402 #define LIBCWD_CHARALLOCATOR_INTERNAL(instance) ::libcwd::_private_:: \
403 allocator_adaptor<char, \
404 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
405 ::libcwd::_private_::instance >, \
407 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
409 #define LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(instance) ::libcwd::_private_:: \
410 allocator_adaptor<char, \
411 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
412 ::libcwd::_private_::instance >, \
414 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
416 #if LIBCWD_THREAD_SAFE
420 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(instance)
421 #else // !LIBCWD_THREAD_SAFE
423 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
424 #endif // !LIBCWD_THREAD_SAFE
426 #if LIBCWD_THREAD_SAFE
430 #define LIBCWD_MT_USERSPACE_ALLOCATOR LIBCWD_CHARALLOCATOR_USERSPACE(userspace_instance)
431 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(multi_threaded_internal_instance)
432 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(multi_threaded_internal_instance)
433 #else // !LIBCWD_THREAD_SAFE
437 #define LIBCWD_MT_USERSPACE_ALLOCATOR std::allocator<char>
438 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
439 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(single_threaded_internal_instance)
440 #endif // !LIBCWD_THREAD_SAFE
446 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(memblk_map_instance) memblk_map_allocator;
449 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(object_files_instance) object_files_allocator;
453 typedef LIBCWD_MT_INTERNAL_ALLOCATOR internal_allocator;
457 typedef LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR auto_internal_allocator;
463 typedef LIBCWD_MT_USERSPACE_ALLOCATOR userspace_allocator;
468 #endif // CWDEBUG_ALLOC
469 #endif // LIBCWD_PRIVATE_ALLOCATOR_H