00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
#ifndef _MT_ALLOCATOR_H
00036
#define _MT_ALLOCATOR_H 1
00037
00038
#include <new>
00039
#include <cstdlib>
00040
#include <bits/functexcept.h>
00041
#include <bits/gthr.h>
00042
#include <bits/atomicity.h>
00043
00044
namespace __gnu_cxx
00045 {
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056 typedef void (*
__destroy_handler)(
void*);
00057
typedef void (*__create_handler)(
void);
00058
00059
class __pool_base
00060 {
00061
public:
00062
00063
00064
struct _Tune
00065 {
00066
00067
00068
00069 size_t _M_align;
00070
00071
00072
00073
00074 size_t _M_max_bytes;
00075
00076
00077
00078 size_t _M_min_bin;
00079
00080
00081
00082
00083
00084
00085 size_t _M_chunk_size;
00086
00087
00088
00089
00090
00091
00092
00093 size_t _M_max_threads;
00094
00095
00096
00097
00098
00099
00100
00101 size_t _M_freelist_headroom;
00102
00103
00104
bool _M_force_new;
00105
00106
explicit
00107 _Tune()
00108 : _M_align(8), _M_max_bytes(128), _M_min_bin(8),
00109 _M_chunk_size(4096 - 4 *
sizeof(
void*)),
00110 _M_max_threads(4096), _M_freelist_headroom(10),
00111 _M_force_new(getenv(
"GLIBCXX_FORCE_NEW") ?
true :
false)
00112 { }
00113
00114
explicit
00115 _Tune(size_t __align, size_t __maxb, size_t __minbin, size_t __chunk,
00116 size_t __maxthreads, size_t __headroom,
bool __force)
00117 : _M_align(__align), _M_max_bytes(__maxb), _M_min_bin(__minbin),
00118 _M_chunk_size(__chunk), _M_max_threads(__maxthreads),
00119 _M_freelist_headroom(__headroom), _M_force_new(__force)
00120 { }
00121 };
00122
00123
const _Tune&
00124 _M_get_options()
const
00125
{
return _M_options; }
00126
00127
void
00128 _M_set_options(_Tune __t)
00129 {
00130
if (!_M_init)
00131 _M_options = __t;
00132 }
00133
00134
bool
00135 _M_check_threshold(size_t __bytes)
00136 {
return __bytes > _M_options._M_max_bytes || _M_options._M_force_new; }
00137
00138 size_t
00139 _M_get_binmap(size_t __bytes)
00140 {
return _M_binmap[__bytes]; }
00141
00142
explicit __pool_base()
00143 : _M_init(
false), _M_options(_Tune()), _M_binmap(NULL) { }
00144
00145
protected:
00146
00147
00148
bool _M_init;
00149
00150
00151 _Tune _M_options;
00152
00153
00154
00155
typedef unsigned short int _Binmap_type;
00156 _Binmap_type* _M_binmap;
00157 };
00158
00159
00160
00161
template<
bool _Thread>
00162
class __pool;
00163
00164
template<>
00165
class __pool<true>;
00166
00167
template<>
00168
class __pool<false>;
00169
00170
00171
#ifdef __GTHREADS
00172
00173
template<>
00174
class __pool<true> :
public __pool_base
00175 {
00176
public:
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
struct _Thread_record
00187 {
00188
00189 _Thread_record*
volatile _M_next;
00190
00191
00192 size_t _M_id;
00193 };
00194
00195
union _Block_record
00196 {
00197
00198 _Block_record*
volatile _M_next;
00199
00200
00201 size_t _M_thread_id;
00202 };
00203
00204
struct _Bin_record
00205 {
00206
00207
00208
00209 _Block_record**
volatile _M_first;
00210
00211
00212
00213
00214
00215 size_t*
volatile _M_free;
00216 size_t*
volatile _M_used;
00217
00218
00219
00220
00221 __gthread_mutex_t* _M_mutex;
00222 };
00223
00224
void
00225 _M_initialize(__destroy_handler __d);
00226
00227
void
00228 _M_initialize_once(__create_handler __c)
00229 {
00230
00231
00232
00233
00234
00235
if (__builtin_expect(_M_init ==
false,
false))
00236 {
00237
if (__gthread_active_p())
00238 __gthread_once(&_M_once, __c);
00239
if (!_M_init)
00240 __c();
00241 }
00242 }
00243
00244
char*
00245 _M_reserve_memory(size_t __bytes,
const size_t __thread_id);
00246
00247
void
00248 _M_reclaim_memory(
char* __p, size_t __bytes);
00249
00250
const _Bin_record&
00251 _M_get_bin(size_t __which)
00252 {
return _M_bin[__which]; }
00253
00254
void
00255 _M_adjust_freelist(
const _Bin_record& __bin, _Block_record* __block,
00256 size_t __thread_id)
00257 {
00258
if (__gthread_active_p())
00259 {
00260 __block->_M_thread_id = __thread_id;
00261 --__bin._M_free[__thread_id];
00262 ++__bin._M_used[__thread_id];
00263 }
00264 }
00265
00266
void
00267 _M_destroy_thread_key(
void* __freelist_pos);
00268
00269 size_t
00270 _M_get_thread_id();
00271
00272
explicit __pool()
00273 : _M_bin(NULL), _M_bin_size(1), _M_thread_freelist(NULL)
00274 {
00275
00276 __gthread_once_t __tmp = __GTHREAD_ONCE_INIT;
00277 _M_once = __tmp;
00278 }
00279
00280
private:
00281
00282
00283
00284 _Bin_record*
volatile _M_bin;
00285
00286
00287 size_t _M_bin_size;
00288
00289 __gthread_once_t _M_once;
00290
00291 _Thread_record* _M_thread_freelist;
00292 };
00293
#endif
00294
00295
00296
template<>
00297
class __pool<false> :
public __pool_base
00298 {
00299
public:
00300
union _Block_record
00301 {
00302
00303 _Block_record*
volatile _M_next;
00304 };
00305
00306
struct _Bin_record
00307 {
00308
00309
00310
00311 _Block_record**
volatile _M_first;
00312 };
00313
00314
void
00315 _M_initialize_once()
00316 {
00317
if (__builtin_expect(_M_init ==
false,
false))
00318 _M_initialize();
00319 }
00320
00321
char*
00322 _M_reserve_memory(size_t __bytes,
const size_t __thread_id);
00323
00324
void
00325 _M_reclaim_memory(
char* __p, size_t __bytes);
00326
00327 size_t
00328 _M_get_thread_id() {
return 0; }
00329
00330
const _Bin_record&
00331 _M_get_bin(size_t __which)
00332 {
return _M_bin[__which]; }
00333
00334
void
00335 _M_adjust_freelist(
const _Bin_record&, _Block_record*, size_t)
00336 { }
00337
00338
explicit __pool()
00339 : _M_bin(NULL), _M_bin_size(1) { }
00340
00341
private:
00342
00343
00344
00345 _Bin_record*
volatile _M_bin;
00346
00347
00348 size_t _M_bin_size;
00349
00350
void
00351 _M_initialize();
00352 };
00353
00354
00355
template<
bool _Thread>
00356
struct __common_pool_policy
00357 {
00358
template<
typename _Tp1,
bool _Thread1 = _Thread>
00359
struct _M_rebind;
00360
00361
template<
typename _Tp1>
00362
struct _M_rebind<_Tp1, true>
00363 {
typedef __common_pool_policy<true> other; };
00364
00365
template<
typename _Tp1>
00366
struct _M_rebind<_Tp1, false>
00367 {
typedef __common_pool_policy<false> other; };
00368
00369
typedef __pool<_Thread> __pool_type;
00370
static __pool_type _S_data;
00371
00372
static __pool_type&
00373 _S_get_pool();
00374
00375
static void
00376 _S_initialize_once()
00377 {
00378
static bool __init;
00379
if (__builtin_expect(__init ==
false,
false))
00380 {
00381 _S_get_pool()._M_initialize_once();
00382 __init =
true;
00383 }
00384 }
00385 };
00386
00387
template<>
00388
struct __common_pool_policy<true>;
00389
00390
#ifdef __GTHREADS
00391
template<>
00392
struct __common_pool_policy<true>
00393 {
00394
template<
typename _Tp1,
bool _Thread1 = true>
00395
struct _M_rebind;
00396
00397
template<
typename _Tp1>
00398
struct _M_rebind<_Tp1, true>
00399 {
typedef __common_pool_policy<true> other; };
00400
00401
template<
typename _Tp1>
00402
struct _M_rebind<_Tp1, false>
00403 {
typedef __common_pool_policy<false> other; };
00404
00405
typedef __pool<true> __pool_type;
00406
static __pool_type _S_data;
00407
00408
static __pool_type&
00409 _S_get_pool();
00410
00411
static void
00412 _S_destroy_thread_key(
void* __freelist_pos)
00413 { _S_get_pool()._M_destroy_thread_key(__freelist_pos); }
00414
00415
static void
00416 _S_initialize()
00417 { _S_get_pool()._M_initialize(_S_destroy_thread_key); }
00418
00419
static void
00420 _S_initialize_once()
00421 {
00422
static bool __init;
00423
if (__builtin_expect(__init ==
false,
false))
00424 {
00425 _S_get_pool()._M_initialize_once(_S_initialize);
00426 __init =
true;
00427 }
00428 }
00429 };
00430
#endif
00431
00432
template<
typename _Tp,
bool _Thread>
00433
struct __per_type_pool_policy
00434 {
00435
template<
typename _Tp1,
bool _Thread1 = _Thread>
00436
struct _M_rebind;
00437
00438
template<
typename _Tp1>
00439
struct _M_rebind<_Tp1, false>
00440 {
typedef __per_type_pool_policy<_Tp1, false> other; };
00441
00442
template<
typename _Tp1>
00443
struct _M_rebind<_Tp1, true>
00444 {
typedef __per_type_pool_policy<_Tp1, true> other; };
00445
00446
typedef __pool<_Thread> __pool_type;
00447
static __pool_type _S_data;
00448
00449
static __pool_type&
00450 _S_get_pool( ) {
return _S_data; }
00451
00452
static void
00453 _S_initialize_once()
00454 {
00455
static bool __init;
00456
if (__builtin_expect(__init ==
false,
false))
00457 {
00458 _S_get_pool()._M_initialize_once();
00459 __init =
true;
00460 }
00461 }
00462 };
00463
00464
template<
typename _Tp,
bool _Thread>
00465 __pool<_Thread>
00466 __per_type_pool_policy<_Tp, _Thread>::_S_data;
00467
00468
template<
typename _Tp>
00469
struct __per_type_pool_policy<_Tp, true>;
00470
00471
#ifdef __GTHREADS
00472
template<
typename _Tp>
00473
struct __per_type_pool_policy<_Tp, true>
00474 {
00475
template<
typename _Tp1,
bool _Thread1 = true>
00476
struct _M_rebind;
00477
00478
template<
typename _Tp1>
00479
struct _M_rebind<_Tp1, false>
00480 {
typedef __per_type_pool_policy<_Tp1, false> other; };
00481
00482
template<
typename _Tp1>
00483
struct _M_rebind<_Tp1, true>
00484 {
typedef __per_type_pool_policy<_Tp1, true> other; };
00485
00486
typedef __pool<true> __pool_type;
00487
static __pool_type _S_data;
00488
00489
static __pool_type&
00490 _S_get_pool( ) {
return _S_data; }
00491
00492
static void
00493 _S_destroy_thread_key(
void* __freelist_pos)
00494 { _S_get_pool()._M_destroy_thread_key(__freelist_pos); }
00495
00496
static void
00497 _S_initialize()
00498 { _S_get_pool()._M_initialize(_S_destroy_thread_key); }
00499
00500
static void
00501 _S_initialize_once()
00502 {
00503
static bool __init;
00504
if (__builtin_expect(__init ==
false,
false))
00505 {
00506 _S_get_pool()._M_initialize_once(_S_initialize);
00507 __init =
true;
00508 }
00509 }
00510 };
00511
00512
template<
typename _Tp>
00513 __pool<true>
00514 __per_type_pool_policy<_Tp, true>::_S_data;
00515
#endif
00516
00517
#ifdef __GTHREADS
00518
typedef __common_pool_policy<true> __default_policy;
00519
#else
00520
typedef __common_pool_policy<false> __default_policy;
00521
#endif
00522
00523
template<
typename _Tp>
00524
class __mt_alloc_base
00525 {
00526
public:
00527
typedef size_t size_type;
00528
typedef ptrdiff_t difference_type;
00529
typedef _Tp* pointer;
00530
typedef const _Tp* const_pointer;
00531
typedef _Tp& reference;
00532
typedef const _Tp& const_reference;
00533
typedef _Tp value_type;
00534
00535 pointer
00536 address(reference __x)
const
00537
{
return &__x; }
00538
00539 const_pointer
00540 address(const_reference __x)
const
00541
{
return &__x; }
00542
00543 size_type
00544 max_size() const throw()
00545 {
return size_t(-1) /
sizeof(_Tp); }
00546
00547
00548
00549
void
00550 construct(pointer __p,
const _Tp& __val)
00551 { ::new(__p) _Tp(__val); }
00552
00553
void
00554 destroy(pointer __p) { __p->~_Tp(); }
00555 };
00556
00557
template<
typename _Tp,
typename _Poolp = __default_policy>
00558
class __mt_alloc :
public __mt_alloc_base<_Tp>, _Poolp
00559 {
00560
public:
00561
typedef size_t size_type;
00562
typedef ptrdiff_t difference_type;
00563
typedef _Tp* pointer;
00564
typedef const _Tp* const_pointer;
00565
typedef _Tp& reference;
00566
typedef const _Tp& const_reference;
00567
typedef _Tp value_type;
00568
typedef _Poolp __policy_type;
00569
typedef typename _Poolp::__pool_type __pool_type;
00570
00571
template<
typename _Tp1,
typename _Poolp1 = _Poolp>
00572
struct rebind
00573 {
00574
typedef typename _Poolp1::template _M_rebind<_Tp1>::other pol_type;
00575
typedef __mt_alloc<_Tp1, pol_type> other;
00576 };
00577
00578 __mt_alloc() throw()
00579 {
00580
00581 }
00582
00583 __mt_alloc(
const __mt_alloc&) throw()
00584 {
00585
00586 }
00587
00588
template<
typename _Tp1,
typename _Poolp1>
00589 __mt_alloc(
const __mt_alloc<_Tp1, _Poolp1>& obj)
throw()
00590 {
00591
00592 }
00593
00594 ~__mt_alloc() throw() { }
00595
00596 pointer
00597 allocate(size_type __n,
const void* = 0);
00598
00599
void
00600 deallocate(pointer __p, size_type __n);
00601
00602
const __pool_base::_Tune
00603 _M_get_options()
00604 {
00605
00606
return __pool_base::_Tune(this->_S_get_pool()._M_get_options());
00607 }
00608
00609
void
00610 _M_set_options(__pool_base::_Tune __t)
00611 { this->_S_get_pool()._M_set_options(__t); }
00612 };
00613
00614
template<
typename _Tp,
typename _Poolp>
00615
typename __mt_alloc<_Tp, _Poolp>::pointer
00616 __mt_alloc<_Tp, _Poolp>::
00617 allocate(size_type __n,
const void*)
00618 {
00619 this->_S_initialize_once();
00620
00621
00622
00623 __pool_type& __pl = this->_S_get_pool();
00624
const size_t __bytes = __n *
sizeof(_Tp);
00625
if (__pl._M_check_threshold(__bytes))
00626 {
00627
void* __ret = ::operator
new(__bytes);
00628
return static_cast<_Tp*>(__ret);
00629 }
00630
00631
00632
const size_t __which = __pl._M_get_binmap(__bytes);
00633
const size_t __thread_id = __pl._M_get_thread_id();
00634
00635
00636
00637
char* __c;
00638
typedef typename __pool_type::_Bin_record _Bin_record;
00639
const _Bin_record& __bin = __pl._M_get_bin(__which);
00640
if (__bin._M_first[__thread_id])
00641 {
00642
00643
typedef typename __pool_type::_Block_record _Block_record;
00644 _Block_record* __block = __bin._M_first[__thread_id];
00645 __bin._M_first[__thread_id] = __bin._M_first[__thread_id]->_M_next;
00646
00647 __pl._M_adjust_freelist(__bin, __block, __thread_id);
00648
const __pool_base::_Tune& __options = __pl._M_get_options();
00649 __c = reinterpret_cast<char*>(__block) + __options._M_align;
00650 }
00651
else
00652 {
00653
00654 __c = __pl._M_reserve_memory(__bytes, __thread_id);
00655 }
00656
return static_cast<_Tp*>(static_cast<void*>(__c));
00657 }
00658
00659
template<
typename _Tp,
typename _Poolp>
00660
void
00661 __mt_alloc<_Tp, _Poolp>::
00662 deallocate(pointer __p, size_type __n)
00663 {
00664
00665
00666 __pool_type& __pl = this->_S_get_pool();
00667
const size_t __bytes = __n *
sizeof(_Tp);
00668
if (__pl._M_check_threshold(__bytes))
00669 ::operator
delete(__p);
00670
else
00671 __pl._M_reclaim_memory(reinterpret_cast<char*>(__p), __bytes);
00672 }
00673
00674
template<
typename _Tp,
typename _Poolp>
00675
inline bool
00676 operator==(
const __mt_alloc<_Tp, _Poolp>&,
const __mt_alloc<_Tp, _Poolp>&)
00677 {
return true; }
00678
00679
template<
typename _Tp,
typename _Poolp>
00680
inline bool
00681 operator!=(
const __mt_alloc<_Tp, _Poolp>&,
const __mt_alloc<_Tp, _Poolp>&)
00682 {
return false; }
00683 }
00684
00685
#endif