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
00038
00039
00040
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 #if __GNUC__ == 3 && __GNUC_MINOR__ == 4
00085 #include <ext/pool_allocator.h>
00086 #endif
00087
00088 namespace libcwd {
00089 namespace _private_ {
00090
00091
00092 int const random_salt = 327665;
00093
00094
00095 int const multi_threaded_internal_instance = -1;
00096 int const single_threaded_internal_instance = -2;
00097 int const userspace_instance = -3;
00098
00099 #if __GNUC__ == 3 && __GNUC_MINOR__ < 4
00100 template<bool needs_lock, int pool_instance>
00101 struct CharPoolAlloc : public std::__default_alloc_template<needs_lock, random_salt + pool_instance> {
00102 typedef char* pointer;
00103 };
00104 #elif __GNUC__ == 3 && __GNUC_MINOR__ == 4 && __GNUC_PATCHLEVEL__ == 0
00105 template<bool needs_lock, int pool_instance>
00106 struct CharPoolAlloc : public __gnu_cxx::__pool_alloc<needs_lock, random_salt + pool_instance> {
00107 typedef char* pointer;
00108 };
00109 #else // gcc 3.4.1 and higher.
00110 template<int pool_instance>
00111 struct char_wrapper {
00112 char c;
00113 };
00114 #if __GNUC__ == 3
00115
00116 template<bool needs_lock, int pool_instance>
00117 class CharPoolAlloc : public __gnu_cxx::__pool_alloc<char_wrapper<pool_instance> > { };
00118 #else // gcc 4.0 and higher.
00119
00120
00121
00122 template<class __pool_type>
00123 struct static_pool_instance {
00124 __pool_type* ptr;
00125 bool M_internal;
00126 static_pool_instance(void) { }
00127
00128
00129
00130 void create(void);
00131 };
00132
00133
00134 template<int pool_instance, bool needs_lock>
00135 struct pool_instance_and_policy {
00136 typedef __gnu_cxx::__pool<needs_lock> __pool_type;
00137 static static_pool_instance<__pool_type> _S_pool_instance;
00138
00139
00140 static __pool_type& _S_get_pool(void)
00141 { return *_S_pool_instance.ptr; }
00142 static void _S_initialize_once(void)
00143 {
00144 static bool __init;
00145 if (__builtin_expect(__init == false, false))
00146 {
00147 _S_pool_instance.create();
00148 _S_pool_instance.ptr->_M_initialize_once();
00149 __init = true;
00150 }
00151 }
00152 };
00153
00154 #ifdef __GTHREADS
00155
00156
00157 template<int pool_instance>
00158 struct pool_instance_and_policy<pool_instance, true>
00159 {
00160 typedef __gnu_cxx::__pool<true> __pool_type;
00161 static static_pool_instance<__pool_type> _S_pool_instance;
00162
00163
00164 static __pool_type& _S_get_pool(void)
00165 { return *_S_pool_instance.ptr; }
00166 static void _S_initialize_once(void)
00167 {
00168 static bool __init;
00169 if (__builtin_expect(__init == false, false))
00170 {
00171 _S_pool_instance.create();
00172 _S_pool_instance.ptr->_M_initialize_once(_S_initialize);
00173 __init = true;
00174 }
00175 }
00176
00177 static void _S_destroy_thread_key(void* __freelist_pos) { _S_get_pool()._M_destroy_thread_key(__freelist_pos); }
00178 static void _S_initialize(void) { _S_get_pool()._M_initialize(_S_destroy_thread_key); }
00179 };
00180
00181 template<int pool_instance>
00182 static_pool_instance<typename pool_instance_and_policy<pool_instance, true>::__pool_type>
00183 pool_instance_and_policy<pool_instance, true>::_S_pool_instance;
00184 #endif // __GTHREADS
00185
00186 template<int pool_instance, bool needs_lock>
00187 static_pool_instance<typename pool_instance_and_policy<pool_instance, needs_lock>::__pool_type>
00188 pool_instance_and_policy<pool_instance, needs_lock>::_S_pool_instance;
00189
00190 template<bool needs_lock, int pool_instance>
00191 class CharPoolAlloc : public __gnu_cxx::__mt_alloc<char, pool_instance_and_policy<pool_instance, needs_lock> > { };
00192 #endif // gcc 4.0 and higher.
00193 #endif // gcc 3.4.1 and higher.
00194
00195
00196 #if CWDEBUG_DEBUG
00197 #define LIBCWD_COMMA_INT_INSTANCE , int instance
00198 #define LIBCWD_COMMA_INSTANCE , instance
00199 #define LIBCWD_DEBUGDEBUG_COMMA(x) , x
00200 #else
00201 #define LIBCWD_COMMA_INT_INSTANCE
00202 #define LIBCWD_COMMA_INSTANCE
00203 #define LIBCWD_DEBUGDEBUG_COMMA(x)
00204 #endif
00205
00206 enum pool_nt {
00207 userspace_pool,
00208 internal_pool,
00209 auto_internal_pool
00210 };
00211
00212
00213
00214
00215
00216 template<typename T, class CharAlloc, pool_nt internal LIBCWD_COMMA_INT_INSTANCE>
00217 class allocator_adaptor {
00218 private:
00219
00220 CharAlloc M_char_allocator;
00221
00222 public:
00223
00224 typedef T value_type;
00225 typedef size_t size_type;
00226 typedef ptrdiff_t difference_type;
00227 typedef T* pointer;
00228 typedef T const* const_pointer;
00229 typedef T& reference;
00230 typedef T const& const_reference;
00231
00232
00233 template <class U>
00234 struct rebind {
00235 typedef allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> other;
00236 };
00237
00238
00239 pointer address(reference value) const { return &value; }
00240 const_pointer address(const_reference value) const { return &value; }
00241
00242
00243 allocator_adaptor(void) throw() { }
00244 allocator_adaptor(allocator_adaptor const& a) : M_char_allocator(a.M_char_allocator) { }
00245 template<class U>
00246 allocator_adaptor(allocator_adaptor<U, CharAlloc, internal LIBCWD_COMMA_INSTANCE> const& a) :
00247 M_char_allocator(a.M_char_allocator) { }
00248 template<class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int instance2)>
00249 friend class allocator_adaptor;
00250 ~allocator_adaptor() throw() { }
00251
00252
00253 size_type max_size(void) const { return M_char_allocator.max_size() / sizeof(T); }
00254
00255
00256 pointer allocate(size_type num);
00257 pointer allocate(size_type num, void const* hint);
00258
00259
00260 void deallocate(pointer p, size_type num);
00261
00262
00263 void construct(pointer p, T const& value) { new ((void*)p) T(value); }
00264
00265
00266 void destroy(pointer p) { p->~T(); }
00267
00268 #if CWDEBUG_DEBUG || CWDEBUG_DEBUGM
00269 private:
00270 static void sanity_check(void);
00271 #endif
00272
00273 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00274 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00275 friend inline
00276 bool operator==(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00277 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00278 template <class T1, class CharAlloc1, pool_nt internal1 LIBCWD_DEBUGDEBUG_COMMA(int inst1),
00279 class T2, class CharAlloc2, pool_nt internal2 LIBCWD_DEBUGDEBUG_COMMA(int inst2)>
00280 friend inline
00281 bool operator!=(allocator_adaptor<T1, CharAlloc1, internal1 LIBCWD_DEBUGDEBUG_COMMA(inst1)> const& a1,
00282 allocator_adaptor<T2, CharAlloc2, internal2 LIBCWD_DEBUGDEBUG_COMMA(inst2)> const& a2);
00283 };
00284
00285 #if LIBCWD_THREAD_SAFE
00286
00287
00288
00289
00290 #define LIBCWD_CHARALLOCATOR_USERSPACE(instance) ::libcwd::_private_:: \
00291 allocator_adaptor<char, \
00292 CharPoolAlloc<true, userspace_instance>, \
00293 userspace_pool \
00294 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00295 #endif
00296
00297
00298
00299
00300
00301
00302
00303 #if LIBCWD_THREAD_SAFE
00304 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) \
00305 ::libcwd::_private_::instance == \
00306 ::libcwd::_private_::multi_threaded_internal_instance || \
00307 ::libcwd::_private_::instance == \
00308 ::libcwd::_private_::memblk_map_instance
00309 #else // !LIBCWD_THREAD_SAFE
00310 #define LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance) false
00311 #endif // !LIBCWD_THREAD_SAFE
00312
00313 #define LIBCWD_CHARALLOCATOR_INTERNAL(instance) ::libcwd::_private_:: \
00314 allocator_adaptor<char, \
00315 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00316 ::libcwd::_private_::instance >, \
00317 internal_pool \
00318 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00319
00320 #define LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(instance) ::libcwd::_private_:: \
00321 allocator_adaptor<char, \
00322 CharPoolAlloc<LIBCWD_ALLOCATOR_POOL_NEEDS_LOCK(instance), \
00323 ::libcwd::_private_::instance >, \
00324 auto_internal_pool \
00325 LIBCWD_DEBUGDEBUG_COMMA(::libcwd::_private_::instance)>
00326
00327 #if LIBCWD_THREAD_SAFE
00328
00329
00330
00331 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(instance)
00332 #else // !LIBCWD_THREAD_SAFE
00333
00334 #define LIBCWD_NS_INTERNAL_ALLOCATOR(instance) LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00335 #endif // !LIBCWD_THREAD_SAFE
00336
00337 #if LIBCWD_THREAD_SAFE
00338
00339
00340
00341 #define LIBCWD_MT_USERSPACE_ALLOCATOR LIBCWD_CHARALLOCATOR_USERSPACE(userspace_instance)
00342 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(multi_threaded_internal_instance)
00343 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(multi_threaded_internal_instance)
00344 #else // !LIBCWD_THREAD_SAFE
00345
00346
00347
00348 #define LIBCWD_MT_USERSPACE_ALLOCATOR std::allocator<char>
00349 #define LIBCWD_MT_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_INTERNAL(single_threaded_internal_instance)
00350 #define LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR LIBCWD_CHARALLOCATOR_AUTO_INTERNAL(single_threaded_internal_instance)
00351 #endif // !LIBCWD_THREAD_SAFE
00352
00353
00354
00355
00356
00357 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(memblk_map_instance) memblk_map_allocator;
00358
00359
00360 typedef LIBCWD_NS_INTERNAL_ALLOCATOR(object_files_instance) object_files_allocator;
00361
00362
00363
00364 typedef LIBCWD_MT_INTERNAL_ALLOCATOR internal_allocator;
00365
00366
00367
00368 typedef LIBCWD_MT_AUTO_INTERNAL_ALLOCATOR auto_internal_allocator;
00369
00370
00371
00372
00373
00374 typedef LIBCWD_MT_USERSPACE_ALLOCATOR userspace_allocator;
00375
00376 }
00377 }
00378
00379 #endif // CWDEBUG_ALLOC
00380 #endif // LIBCWD_PRIVATE_ALLOCATOR_H
00381