00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00018 #ifndef LIBCWD_PRIVATE_ALLOCATOR_H
00019 #define LIBCWD_PRIVATE_ALLOCATOR_H
00020
00021 #ifndef LIBCWD_CONFIG_H
00022 #include <libcwd/config.h>
00023 #endif
00024
00025 #if CWDEBUG_ALLOC // This file is not used when --disable-alloc was used.
00026
00027 #ifndef LIBCWD_PRIVATE_MUTEX_INSTANCES_H
00028 #include <libcwd/private_mutex_instances.h>
00029 #endif
00030 #ifndef LIBCWD_CORE_DUMP_H
00031 #include <libcwd/core_dump.h>
00032 #endif
00033 #ifndef LIBCW_CSTDDEF
00034 #define LIBCW_CSTDDEF
00035 #include <cstddef>
00036 #endif
00037 #if __GNUC__ > 3 && LIBCWD_THREAD_SAFE
00038 #include <libcwd/private_mutex.h>
00039 #endif
00040 #include <memory>
00041 #include <limits>
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 #if __GNUC__ == 3 && __GNUC_MINOR__ == 4
00090 #include <ext/pool_allocator.h>
00091 #endif
00092
00093 namespace libcwd {
00094 namespace _private_ {
00095
00096
00097 int const random_salt = 327665;
00098
00099
00100 int const multi_threaded_internal_instance = -1;
00101 int const single_threaded_internal_instance = -2;
00102 int const userspace_instance = -3;
00103
00104
00105 #if __GNUC__ == 3 && __GNUC_MINOR__ < 4
00106 template<bool needs_lock, int pool_instance>
00107 struct CharPoolAlloc : public std::__default_alloc_template<needs_lock, random_salt + pool_instance> {
00108 typedef char* pointer;
00109 };
00110 #elif __GNUC__ == 3 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 0
00111 template<bool needs_lock, int pool_instance>
00112 struct CharPoolAlloc : public __gnu_cxx::__pool_alloc<needs_lock, random_salt + pool_instance> {
00113 typedef char* pointer;
00114 };
00115 #elif __GNUC__ == 3
00116
00117 template<int pool_instance>
00118 struct char_wrapper {
00119 char c;
00120 };
00121
00122 template<bool needs_lock, int pool_instance>
00123 class CharPoolAlloc : public __gnu_cxx::__pool_alloc<char_wrapper<pool_instance> > { };
00124 #else // gcc 4.0 and higher.
00125
00126
00127 static size_t const maximum_size_exp = 10;
00128
00129
00130 static size_t const maximum_size = (1U << maximum_size_exp);
00131
00132 struct Node {
00133 Node* M_next;
00134 Node* M_prev;
00135
00136 Node* next(void) const { return M_next; }
00137 Node* prev(void) const { return M_prev; }
00138
00139 void unlink(void)
00140 {
00141 M_prev->M_next = M_next;
00142 M_next->M_prev = M_prev;
00143 }
00144 };
00145
00146
00147 template <unsigned int N> struct log2 { enum { result = 1 + log2<N/2>::result }; };
00148 template<> struct log2<0> { enum { result = -1 }; };
00149 static size_t const minimum_size_exp = log2<sizeof(Node) - 1>::result + 1;
00150
00151 static size_t const minimum_size = (1U << minimum_size_exp);
00152
00153 static int const bucket_sizes = maximum_size_exp - minimum_size_exp + 1;
00154
00155 struct List : public Node {
00156 bool empty(void) const { return M_next == this; }
00157 void insert(Node* node)
00158 {
00159 node->M_prev = this;
00160 node->M_next = M_next;
00161 M_next->M_prev = node;
00162 M_next = node;
00163 }
00164 void insert_back(Node* node)
00165 {
00166 node->M_prev = M_prev;
00167 node->M_next = this;
00168 M_prev->M_next = node;
00169 M_prev = node;
00170 }
00171 private:
00172 using Node::next;
00173 using Node::prev;
00174 };
00175
00176 struct ChunkNode : public Node {
00177
00178
00179
00180 ChunkNode* next(void) const { return static_cast<ChunkNode*>(M_next); }
00181 ChunkNode* prev(void) const { return static_cast<ChunkNode*>(M_prev); }
00182 };
00183
00184 struct ChunkList : public List {
00185 unsigned int M_used_count;
00186 ChunkNode* begin(void) const { return static_cast<ChunkNode*>(M_next); }
00187 Node const* end(void) const { return this; }
00188 };
00189
00190 struct BlockNode : public Node {
00191 ChunkList M_chunks;
00192 ChunkNode M_data[1];
00193
00194 BlockNode* next(void) const { return static_cast<BlockNode*>(M_next); }
00195 BlockNode* prev(void) const { return static_cast<BlockNode*>(M_prev); }
00196 };
00197
00198 struct BlockList : public List {
00199 unsigned int* M_count_ptr;
00200 unsigned short M_internal;
00201
00202 BlockNode* begin(void) const { return static_cast<BlockNode*>(M_next); }
00203 Node const* end(void) const { return this; }
00204
00205 void initialize(unsigned int* count_ptr, unsigned short internal);
00206 void uninitialize(void);
00207 ~BlockList() { uninitialize(); }
00208 #if CWDEBUG_DEBUG
00209 void consistency_check(void);
00210 #endif
00211 };
00212
00213 struct TSD_st;
00214
00215 struct FreeList {
00216 #if LIBCWD_THREAD_SAFE
00217 pthread_mutex_t M_mutex;
00218 static pthread_mutex_t S_mutex;
00219 #endif
00220 bool M_initialized;
00221 unsigned int M_count[bucket_sizes];
00222 unsigned short M_keep[bucket_sizes];
00223 BlockList M_list_notfull[bucket_sizes];
00224 BlockList M_list_full[bucket_sizes];
00225
00226 #if LIBCWD_THREAD_SAFE
00227 void initialize(TSD_st& __libcwd_tsd);
00228 #else
00229 void initialize(void);
00230 #endif
00231 void uninitialize(void);
00232 ~FreeList() { uninitialize(); }
00233 char* allocate(int power, size_t size);
00234 void deallocate(char* p, int power, size_t size);
00235 #if CWDEBUG_DEBUG
00236 void consistency_check(void);
00237 #endif
00238 };
00239
00240 template<bool needs_lock, int pool_instance>
00241 class CharPoolAlloc {
00242 private:
00243 static FreeList S_freelist;
00244
00245 public:
00246
00247 typedef char value_type;
00248 typedef size_t size_type;
00249 typedef ptrdiff_t difference_type;
00250 typedef char* pointer;
00251 typedef char const* const_pointer;
00252 typedef char& reference;
00253 typedef char const& const_reference;
00254
00255
00256 #if LIBCWD_THREAD_SAFE
00257 pointer allocate(size_type num, TSD_st&);
00258 #else
00259 pointer allocate(size_type num);
00260 #endif
00261
00262
00263 #if LIBCWD_THREAD_SAFE
00264 void deallocate(pointer p, size_type num, TSD_st&);
00265 #else
00266 void deallocate(pointer p, size_type num);
00267 #endif
00268
00269 template <bool needs_lock1, int pool_instance1,
00270 bool needs_lock2, int pool_instance2>
00271 friend inline
00272 bool operator==(CharPoolAlloc<needs_lock1, pool_instance1> const&,
00273 CharPoolAlloc<needs_lock2, pool_instance2> const&);
00274 template <bool needs_lock1, int pool_instance1,
00275 bool needs_lock2, int pool_instance2>
00276 friend inline
00277 bool operator!=(CharPoolAlloc<needs_lock1, pool_instance1> const&,
00278 CharPoolAlloc<needs_lock2, pool_instance2> const&);
00279
00280 size_type max_size(void) const { return std::numeric_limits<size_type>::max(); }
00281 };
00282 #endif // gcc 4.0 and higher.
00283
00284
00285 #if CWDEBUG_DEBUG
00286 #define LIBCWD_COMMA_INT_INSTANCE , int instance
00287 #define LIBCWD_COMMA_INSTANCE , instance
00288 #define LIBCWD_DEBUGDEBUG_COMMA(x) , x
00289 #else
00290 #define LIBCWD_COMMA_INT_INSTANCE
00291 #define LIBCWD_COMMA_INSTANCE
00292 #define LIBCWD_DEBUGDEBUG_COMMA(x)
00293 #endif
00294
00295 enum pool_nt {
00296 userspace_pool,
00297 internal_pool,
00298 auto_internal_pool
00299 };
00300
00301
00302
00303
00304
00305 template<typename T, class CharAlloc, pool_nt internal LIBCWD_COMMA_INT_INSTANCE>
00306 class allocator_adaptor {
00307 private:
00308
00309 CharAlloc M_char_allocator;
00310
00311 public:
00312
00313 typedef T value_type;
00314 typedef size_t size_type;
00315 typedef ptrdiff_t difference_type;
00316 typedef T* pointer;
00317 typedef T const* const_pointer;
00318 typedef T& reference;
00319 typedef T const& const_reference;
00320
00321
00322 template <class U>
00323 struct rebind {
00324 typedef allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> other;
00325 };
00326
00327
00328 pointer address(reference value) const { return &value; }
00329 const_pointer address(const_reference value) const { return &value; }
00330
00331
00332 allocator_adaptor(void) throw() { }
00333 allocator_adaptor(allocator_adaptor const& a) : M_char_allocator(a.M_char_allocator) { }
00334 template<class U>
00335 allocator_adaptor(allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> const& a) :
00336 M_char_allocator(a.M_char_allocator) { }
00337 template<class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int instance2)>
00338 friend class allocator_adaptor;
00339 ~allocator_adaptor() throw() { }
00340
00341
00342 size_type max_size(void) const { return M_char_allocator.max_size() / sizeof(T); }
00343
00344
00345 pointer allocate(size_type num);
00346 pointer allocate(size_type num, void const* hint);
00347
00348
00349 void deallocate(pointer p, size_type num);
00350
00351
00352 void construct(pointer p, T const& value) { new ((void*)p) T(value); }
00353
00354
00355 void destroy(pointer p) { p->~T(); }
00356
00357 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGM
00358 private:
00359 static void sanity_check(void);
00360 #endif
00361
00362 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00363 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00364 friend inline
00365 bool operator==(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00366 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00367 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00368 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00369 friend inline
00370 bool operator!=(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00371 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00372 };
00373
00374 #if LIBCWD_THREAD_SAFE
00375
00376
00377
00378
00379 #define LIBCWD_CHARALLOCATOR_USERSPACE(instance) ::libcwd::_private_:: \
00380 allocator_adaptor<char, \
00381 CharPoolAlloc<true, userspace_instance>, \
00382 userspace_pool \
00383 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00384 #endif
00385
00386
00387
00388
00389
00390
00391
00392 #if LIBCWD_THREAD_SAFE
00393 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) \
00394 ::libcwd::_private_::instance == \
00395 ::libcwd::_private_::multi_threaded_internal_instance || \
00396 ::libcwd::_private_::instance == \
00397 ::libcwd::_private_::memblk_map_instance
00398 #else // !LIBCWD_THREAD_SAFE
00399 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) false
00400 #endif // !LIBCWD_THREAD_SAFE
00401
00402 #define LIBCWD_CHARALLOCATOR_INTERNAL(instance) ::libcwd::_private_:: \
00403 allocator_adaptor<char, \
00404 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00405 ::libcwd::_private_::instance >, \
00406 internal_pool \
00407 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00408
00409 #define LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(instance) ::libcwd::_private_:: \
00410 allocator_adaptor<char, \
00411 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00412 ::libcwd::_private_::instance >, \
00413 auto_internal_pool \
00414 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00415
00416 #if LIBCWD_THREAD_SAFE
00417
00418
00419
00420 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(instance)
00421 #else // !LIBCWD_THREAD_SAFE
00422
00423 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00424 #endif // !LIBCWD_THREAD_SAFE
00425
00426 #if LIBCWD_THREAD_SAFE
00427
00428
00429
00430 #define LIBCWD_MT_USERSPACE_ALLOCATOR LIBCWD_CHARALLOCATOR_USERSPACE(userspace_instance)
00431 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(multi_threaded_internal_instance)
00432 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(multi_threaded_internal_instance)
00433 #else // !LIBCWD_THREAD_SAFE
00434
00435
00436
00437 #define LIBCWD_MT_USERSPACE_ALLOCATOR std::allocator<char>
00438 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00439 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(single_threaded_internal_instance)
00440 #endif // !LIBCWD_THREAD_SAFE
00441
00442
00443
00444
00445
00446 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(memblk_map_instance) memblk_map_allocator;
00447
00448
00449 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(object_files_instance) object_files_allocator;
00450
00451
00452
00453 typedef LIBCWD_MT_INTERNAL_ALLOCATOR internal_allocator;
00454
00455
00456
00457 typedef LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR auto_internal_allocator;
00458
00459
00460
00461
00462
00463 typedef LIBCWD_MT_USERSPACE_ALLOCATOR userspace_allocator;
00464
00465 }
00466 }
00467
00468 #endif // CWDEBUG_ALLOC
00469 #endif // LIBCWD_PRIVATE_ALLOCATOR_H
00470