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 #endif
00219 bool M_initialized;
00220 unsigned int M_count[bucket_sizes];
00221 unsigned short M_keep[bucket_sizes];
00222 BlockList M_list_notfull[bucket_sizes];
00223 BlockList M_list_full[bucket_sizes];
00224
00225 #if LIBCWD_THREAD_SAFE
00226 void initialize(TSD_st& __libcwd_tsd);
00227 #else
00228 void initialize(void);
00229 #endif
00230 void uninitialize(void);
00231 ~FreeList() { uninitialize(); }
00232 char* allocate(int power, size_t size);
00233 void deallocate(char* p, int power, size_t size);
00234 #if CWDEBUG_DEBUG
00235 void consistency_check(void);
00236 #endif
00237 };
00238
00239 template<bool needs_lock, int pool_instance>
00240 class CharPoolAlloc {
00241 private:
00242 static FreeList S_freelist;
00243
00244 public:
00245
00246 typedef char value_type;
00247 typedef size_t size_type;
00248 typedef ptrdiff_t difference_type;
00249 typedef char* pointer;
00250 typedef char const* const_pointer;
00251 typedef char& reference;
00252 typedef char const& const_reference;
00253
00254
00255 #if LIBCWD_THREAD_SAFE
00256 pointer allocate(size_type num, TSD_st&);
00257 #else
00258 pointer allocate(size_type num);
00259 #endif
00260
00261
00262 #if LIBCWD_THREAD_SAFE
00263 void deallocate(pointer p, size_type num, TSD_st&);
00264 #else
00265 void deallocate(pointer p, size_type num);
00266 #endif
00267
00268 template <bool needs_lock1, int pool_instance1,
00269 bool needs_lock2, int pool_instance2>
00270 friend inline
00271 bool operator==(CharPoolAlloc<needs_lock1, pool_instance1> const&,
00272 CharPoolAlloc<needs_lock2, pool_instance2> const&);
00273 template <bool needs_lock1, int pool_instance1,
00274 bool needs_lock2, int pool_instance2>
00275 friend inline
00276 bool operator!=(CharPoolAlloc<needs_lock1, pool_instance1> const&,
00277 CharPoolAlloc<needs_lock2, pool_instance2> const&);
00278
00279 size_type max_size(void) const { return std::numeric_limits<size_type>::max(); }
00280 };
00281 #endif // gcc 4.0 and higher.
00282
00283
00284 #if CWDEBUG_DEBUG
00285 #define LIBCWD_COMMA_INT_INSTANCE , int instance
00286 #define LIBCWD_COMMA_INSTANCE , instance
00287 #define LIBCWD_DEBUGDEBUG_COMMA(x) , x
00288 #else
00289 #define LIBCWD_COMMA_INT_INSTANCE
00290 #define LIBCWD_COMMA_INSTANCE
00291 #define LIBCWD_DEBUGDEBUG_COMMA(x)
00292 #endif
00293
00294 enum pool_nt {
00295 userspace_pool,
00296 internal_pool,
00297 auto_internal_pool
00298 };
00299
00300
00301
00302
00303
00304 template<typename T, class CharAlloc, pool_nt internal LIBCWD_COMMA_INT_INSTANCE>
00305 class allocator_adaptor {
00306 private:
00307
00308 CharAlloc M_char_allocator;
00309
00310 public:
00311
00312 typedef T value_type;
00313 typedef size_t size_type;
00314 typedef ptrdiff_t difference_type;
00315 typedef T* pointer;
00316 typedef T const* const_pointer;
00317 typedef T& reference;
00318 typedef T const& const_reference;
00319
00320
00321 template <class U>
00322 struct rebind {
00323 typedef allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> other;
00324 };
00325
00326
00327 pointer address(reference value) const { return &value; }
00328 const_pointer address(const_reference value) const { return &value; }
00329
00330
00331 allocator_adaptor(void) throw() { }
00332 allocator_adaptor(allocator_adaptor const& a) : M_char_allocator(a.M_char_allocator) { }
00333 template<class U>
00334 allocator_adaptor(allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> const& a) :
00335 M_char_allocator(a.M_char_allocator) { }
00336 template<class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int instance2)>
00337 friend class allocator_adaptor;
00338 ~allocator_adaptor() throw() { }
00339
00340
00341 size_type max_size(void) const { return M_char_allocator.max_size() / sizeof(T); }
00342
00343
00344 pointer allocate(size_type num);
00345 pointer allocate(size_type num, void const* hint);
00346
00347
00348 void deallocate(pointer p, size_type num);
00349
00350
00351 void construct(pointer p, T const& value) { new ((void*)p) T(value); }
00352
00353
00354 void destroy(pointer p) { p->~T(); }
00355
00356 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGM
00357 private:
00358 static void sanity_check(void);
00359 #endif
00360
00361 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00362 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00363 friend inline
00364 bool operator==(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00365 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00366 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00367 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00368 friend inline
00369 bool operator!=(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00370 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00371 };
00372
00373 #if LIBCWD_THREAD_SAFE
00374
00375
00376
00377
00378 #define LIBCWD_CHARALLOCATOR_USERSPACE(instance) ::libcwd::_private_:: \
00379 allocator_adaptor<char, \
00380 CharPoolAlloc<true, userspace_instance>, \
00381 userspace_pool \
00382 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00383 #endif
00384
00385
00386
00387
00388
00389
00390
00391 #if LIBCWD_THREAD_SAFE
00392 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) \
00393 ::libcwd::_private_::instance == \
00394 ::libcwd::_private_::multi_threaded_internal_instance || \
00395 ::libcwd::_private_::instance == \
00396 ::libcwd::_private_::memblk_map_instance
00397 #else // !LIBCWD_THREAD_SAFE
00398 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) false
00399 #endif // !LIBCWD_THREAD_SAFE
00400
00401 #define LIBCWD_CHARALLOCATOR_INTERNAL(instance) ::libcwd::_private_:: \
00402 allocator_adaptor<char, \
00403 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00404 ::libcwd::_private_::instance >, \
00405 internal_pool \
00406 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00407
00408 #define LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(instance) ::libcwd::_private_:: \
00409 allocator_adaptor<char, \
00410 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00411 ::libcwd::_private_::instance >, \
00412 auto_internal_pool \
00413 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00414
00415 #if LIBCWD_THREAD_SAFE
00416
00417
00418
00419 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(instance)
00420 #else // !LIBCWD_THREAD_SAFE
00421
00422 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00423 #endif // !LIBCWD_THREAD_SAFE
00424
00425 #if LIBCWD_THREAD_SAFE
00426
00427
00428
00429 #define LIBCWD_MT_USERSPACE_ALLOCATOR LIBCWD_CHARALLOCATOR_USERSPACE(userspace_instance)
00430 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(multi_threaded_internal_instance)
00431 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(multi_threaded_internal_instance)
00432 #else // !LIBCWD_THREAD_SAFE
00433
00434
00435
00436 #define LIBCWD_MT_USERSPACE_ALLOCATOR std::allocator<char>
00437 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00438 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(single_threaded_internal_instance)
00439 #endif // !LIBCWD_THREAD_SAFE
00440
00441
00442
00443
00444
00445 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(memblk_map_instance) memblk_map_allocator;
00446
00447
00448 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(object_files_instance) object_files_allocator;
00449
00450
00451
00452 typedef LIBCWD_MT_INTERNAL_ALLOCATOR internal_allocator;
00453
00454
00455
00456 typedef LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR auto_internal_allocator;
00457
00458
00459
00460
00461
00462 typedef LIBCWD_MT_USERSPACE_ALLOCATOR userspace_allocator;
00463
00464 }
00465 }
00466
00467 #endif // CWDEBUG_ALLOC
00468 #endif // LIBCWD_PRIVATE_ALLOCATOR_H
00469