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
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 #if __GNUC__ == 3 && __GNUC_MINOR__ == 4
00089 #include <ext/pool_allocator.h>
00090 #endif
00091
00092 namespace libcwd {
00093 namespace _private_ {
00094
00095
00096 int const random_salt = 327665;
00097
00098
00099 int const multi_threaded_internal_instance = -1;
00100 int const single_threaded_internal_instance = -2;
00101 int const userspace_instance = -3;
00102
00103
00104 #if __GNUC__ == 3 && __GNUC_MINOR__ < 4
00105 template<bool needs_lock, int pool_instance>
00106 struct CharPoolAlloc : public std::__default_alloc_template<needs_lock, random_salt + pool_instance> {
00107 typedef char* pointer;
00108 };
00109 #elif __GNUC__ == 3 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 0
00110 template<bool needs_lock, int pool_instance>
00111 struct CharPoolAlloc : public __gnu_cxx::__pool_alloc<needs_lock, random_salt + pool_instance> {
00112 typedef char* pointer;
00113 };
00114 #elif __GNUC__ == 3
00115
00116 template<int pool_instance>
00117 struct char_wrapper {
00118 char c;
00119 };
00120
00121 template<bool needs_lock, int pool_instance>
00122 class CharPoolAlloc : public __gnu_cxx::__pool_alloc<char_wrapper<pool_instance> > { };
00123 #else // gcc 4.0 and higher.
00124
00125
00126 static size_t const maximum_size_exp = 10;
00127
00128
00129 static size_t const maximum_size = (1U << maximum_size_exp);
00130
00131 struct Node {
00132 Node* M_next;
00133 Node* M_prev;
00134
00135 Node* next(void) const { return M_next; }
00136 Node* prev(void) const { return M_prev; }
00137
00138 void unlink(void)
00139 {
00140 M_prev->M_next = M_next;
00141 M_next->M_prev = M_prev;
00142 }
00143 };
00144
00145
00146 template <unsigned int N> struct log2 { enum { result = 1 + log2<N/2>::result }; };
00147 template<> struct log2<0> { enum { result = -1 }; };
00148 static size_t const minimum_size_exp = log2<sizeof(Node) - 1>::result + 1;
00149
00150 static size_t const minimum_size = (1U << minimum_size_exp);
00151
00152 static int const bucket_sizes = maximum_size_exp - minimum_size_exp + 1;
00153
00154 struct List : public Node {
00155 bool empty(void) const { return M_next == this; }
00156 void insert(Node* node)
00157 {
00158 node->M_prev = M_next->M_prev;
00159 node->M_next = M_next;
00160 M_next->M_prev = node;
00161 M_next = node;
00162 }
00163 private:
00164 using Node::next;
00165 using Node::prev;
00166 };
00167
00168 struct ChunkNode : public Node {
00169
00170
00171
00172 ChunkNode* next(void) const { return static_cast<ChunkNode*>(M_next); }
00173 ChunkNode* prev(void) const { return static_cast<ChunkNode*>(M_prev); }
00174 };
00175
00176 struct ChunkList : public List {
00177 unsigned int M_used_count;
00178 ChunkNode* begin(void) const { return static_cast<ChunkNode*>(M_next); }
00179 Node const* end(void) const { return this; }
00180 };
00181
00182 struct BlockNode : public Node {
00183 ChunkList M_chunks;
00184 ChunkNode M_data[1];
00185
00186 BlockNode* next(void) const { return static_cast<BlockNode*>(M_next); }
00187 BlockNode* prev(void) const { return static_cast<BlockNode*>(M_prev); }
00188 };
00189
00190 struct BlockList : public List {
00191 unsigned int M_count;
00192 unsigned short M_keep;
00193 unsigned short M_internal;
00194
00195 BlockNode* begin(void) const { return static_cast<BlockNode*>(M_next); }
00196 Node const* end(void) const { return this; }
00197
00198 void initialize(unsigned short internal);
00199 void uninitialize(void);
00200 ~BlockList() { uninitialize(); }
00201 };
00202
00203 struct TSD_st;
00204
00205 struct FreeList {
00206 #if LIBCWD_THREAD_SAFE
00207 pthread_mutex_t M_mutex;
00208 #endif
00209 bool M_initialized;
00210 BlockList M_list[bucket_sizes];
00211
00212 #if LIBCWD_THREAD_SAFE
00213 void initialize(TSD_st& __libcwd_tsd);
00214 #else
00215 void initialize(void);
00216 #endif
00217 char* allocate(int power, size_t size);
00218 void deallocate(char* p, int power, size_t size);
00219 };
00220
00221 template<bool needs_lock, int pool_instance>
00222 class CharPoolAlloc {
00223 private:
00224 static FreeList S_freelist;
00225
00226 public:
00227
00228 typedef char value_type;
00229 typedef size_t size_type;
00230 typedef ptrdiff_t difference_type;
00231 typedef char* pointer;
00232 typedef char const* const_pointer;
00233 typedef char& reference;
00234 typedef char const& const_reference;
00235
00236
00237 #if LIBCWD_THREAD_SAFE
00238 pointer allocate(size_type num, TSD_st&);
00239 #else
00240 pointer allocate(size_type num);
00241 #endif
00242
00243
00244 #if LIBCWD_THREAD_SAFE
00245 void deallocate(pointer p, size_type num, TSD_st&);
00246 #else
00247 void deallocate(pointer p, size_type num);
00248 #endif
00249
00250 template <bool needs_lock1, int pool_instance1,
00251 bool needs_lock2, int pool_instance2>
00252 friend inline
00253 bool operator==(CharPoolAlloc<needs_lock1, pool_instance1> const&,
00254 CharPoolAlloc<needs_lock2, pool_instance2> const&);
00255 template <bool needs_lock1, int pool_instance1,
00256 bool needs_lock2, int pool_instance2>
00257 friend inline
00258 bool operator!=(CharPoolAlloc<needs_lock1, pool_instance1> const&,
00259 CharPoolAlloc<needs_lock2, pool_instance2> const&);
00260 };
00261 #endif // gcc 4.0 and higher.
00262
00263
00264 #if CWDEBUG_DEBUG
00265 #define LIBCWD_COMMA_INT_INSTANCE , int instance
00266 #define LIBCWD_COMMA_INSTANCE , instance
00267 #define LIBCWD_DEBUGDEBUG_COMMA(x) , x
00268 #else
00269 #define LIBCWD_COMMA_INT_INSTANCE
00270 #define LIBCWD_COMMA_INSTANCE
00271 #define LIBCWD_DEBUGDEBUG_COMMA(x)
00272 #endif
00273
00274 enum pool_nt {
00275 userspace_pool,
00276 internal_pool,
00277 auto_internal_pool
00278 };
00279
00280
00281
00282
00283
00284 template<typename T, class CharAlloc, pool_nt internal LIBCWD_COMMA_INT_INSTANCE>
00285 class allocator_adaptor {
00286 private:
00287
00288 CharAlloc M_char_allocator;
00289
00290 public:
00291
00292 typedef T value_type;
00293 typedef size_t size_type;
00294 typedef ptrdiff_t difference_type;
00295 typedef T* pointer;
00296 typedef T const* const_pointer;
00297 typedef T& reference;
00298 typedef T const& const_reference;
00299
00300
00301 template <class U>
00302 struct rebind {
00303 typedef allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> other;
00304 };
00305
00306
00307 pointer address(reference value) const { return &value; }
00308 const_pointer address(const_reference value) const { return &value; }
00309
00310
00311 allocator_adaptor(void) throw() { }
00312 allocator_adaptor(allocator_adaptor const& a) : M_char_allocator(a.M_char_allocator) { }
00313 template<class U>
00314 allocator_adaptor(allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> const& a) :
00315 M_char_allocator(a.M_char_allocator) { }
00316 template<class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int instance2)>
00317 friend class allocator_adaptor;
00318 ~allocator_adaptor() throw() { }
00319
00320
00321 size_type max_size(void) const { return M_char_allocator.max_size() / sizeof(T); }
00322
00323
00324 pointer allocate(size_type num);
00325 pointer allocate(size_type num, void const* hint);
00326
00327
00328 void deallocate(pointer p, size_type num);
00329
00330
00331 void construct(pointer p, T const& value) { new ((void*)p) T(value); }
00332
00333
00334 void destroy(pointer p) { p->~T(); }
00335
00336 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGM
00337 private:
00338 static void sanity_check(void);
00339 #endif
00340
00341 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00342 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00343 friend inline
00344 bool operator==(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00345 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00346 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00347 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00348 friend inline
00349 bool operator!=(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00350 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00351 };
00352
00353 #if LIBCWD_THREAD_SAFE
00354
00355
00356
00357
00358 #define LIBCWD_CHARALLOCATOR_USERSPACE(instance) ::libcwd::_private_:: \
00359 allocator_adaptor<char, \
00360 CharPoolAlloc<true, userspace_instance>, \
00361 userspace_pool \
00362 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00363 #endif
00364
00365
00366
00367
00368
00369
00370
00371 #if LIBCWD_THREAD_SAFE
00372 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) \
00373 ::libcwd::_private_::instance == \
00374 ::libcwd::_private_::multi_threaded_internal_instance || \
00375 ::libcwd::_private_::instance == \
00376 ::libcwd::_private_::memblk_map_instance
00377 #else // !LIBCWD_THREAD_SAFE
00378 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) false
00379 #endif // !LIBCWD_THREAD_SAFE
00380
00381 #define LIBCWD_CHARALLOCATOR_INTERNAL(instance) ::libcwd::_private_:: \
00382 allocator_adaptor<char, \
00383 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00384 ::libcwd::_private_::instance >, \
00385 internal_pool \
00386 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00387
00388 #define LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(instance) ::libcwd::_private_:: \
00389 allocator_adaptor<char, \
00390 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00391 ::libcwd::_private_::instance >, \
00392 auto_internal_pool \
00393 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00394
00395 #if LIBCWD_THREAD_SAFE
00396
00397
00398
00399 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(instance)
00400 #else // !LIBCWD_THREAD_SAFE
00401
00402 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00403 #endif // !LIBCWD_THREAD_SAFE
00404
00405 #if LIBCWD_THREAD_SAFE
00406
00407
00408
00409 #define LIBCWD_MT_USERSPACE_ALLOCATOR LIBCWD_CHARALLOCATOR_USERSPACE(userspace_instance)
00410 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(multi_threaded_internal_instance)
00411 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(multi_threaded_internal_instance)
00412 #else // !LIBCWD_THREAD_SAFE
00413
00414
00415
00416 #define LIBCWD_MT_USERSPACE_ALLOCATOR std::allocator<char>
00417 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00418 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(single_threaded_internal_instance)
00419 #endif // !LIBCWD_THREAD_SAFE
00420
00421
00422
00423
00424
00425 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(memblk_map_instance) memblk_map_allocator;
00426
00427
00428 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(object_files_instance) object_files_allocator;
00429
00430
00431
00432 typedef LIBCWD_MT_INTERNAL_ALLOCATOR internal_allocator;
00433
00434
00435
00436 typedef LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR auto_internal_allocator;
00437
00438
00439
00440
00441
00442 typedef LIBCWD_MT_USERSPACE_ALLOCATOR userspace_allocator;
00443
00444 }
00445 }
00446
00447 #endif
00448 #endif
00449