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
00036
00037
00038
00039
00040
00041
00042
00048 #ifndef __GLIBCPP_INTERNAL_ALLOC_H
00049 #define __GLIBCPP_INTERNAL_ALLOC_H
00050
00081 #include <cstddef>
00082 #include <cstdlib>
00083 #include <cstring>
00084 #include <cassert>
00085 #include <bits/functexcept.h>
00086 #include <bits/stl_threads.h>
00087
00088 namespace std
00089 {
00098 class __new_alloc
00099 {
00100 public:
00101 static void*
00102 allocate(size_t __n)
00103 { return ::operator new(__n); }
00104
00105 static void
00106 deallocate(void* __p, size_t)
00107 { ::operator delete(__p); }
00108 };
00109
00110
00121 template <int __inst>
00122 class __malloc_alloc_template
00123 {
00124 private:
00125 static void* _S_oom_malloc(size_t);
00126 static void* _S_oom_realloc(void*, size_t);
00127 static void (* __malloc_alloc_oom_handler)();
00128
00129 public:
00130 static void*
00131 allocate(size_t __n)
00132 {
00133 void* __result = malloc(__n);
00134 if (0 == __result) __result = _S_oom_malloc(__n);
00135 return __result;
00136 }
00137
00138 static void
00139 deallocate(void* __p, size_t )
00140 { free(__p); }
00141
00142 static void*
00143 reallocate(void* __p, size_t , size_t __new_sz)
00144 {
00145 void* __result = realloc(__p, __new_sz);
00146 if (0 == __result) __result = _S_oom_realloc(__p, __new_sz);
00147 return __result;
00148 }
00149
00150 static void (* __set_malloc_handler(void (*__f)()))()
00151 {
00152 void (* __old)() = __malloc_alloc_oom_handler;
00153 __malloc_alloc_oom_handler = __f;
00154 return(__old);
00155 }
00156 };
00157
00158
00159 template <int __inst>
00160 void (* __malloc_alloc_template<__inst>::__malloc_alloc_oom_handler)() = 0;
00161
00162 template <int __inst>
00163 void*
00164 __malloc_alloc_template<__inst>::_S_oom_malloc(size_t __n)
00165 {
00166 void (* __my_malloc_handler)();
00167 void* __result;
00168
00169 for (;;)
00170 {
00171 __my_malloc_handler = __malloc_alloc_oom_handler;
00172 if (0 == __my_malloc_handler)
00173 std::__throw_bad_alloc();
00174 (*__my_malloc_handler)();
00175 __result = malloc(__n);
00176 if (__result)
00177 return(__result);
00178 }
00179 }
00180
00181 template <int __inst>
00182 void*
00183 __malloc_alloc_template<__inst>::_S_oom_realloc(void* __p, size_t __n)
00184 {
00185 void (* __my_malloc_handler)();
00186 void* __result;
00187
00188 for (;;)
00189 {
00190 __my_malloc_handler = __malloc_alloc_oom_handler;
00191 if (0 == __my_malloc_handler)
00192 std::__throw_bad_alloc();
00193 (*__my_malloc_handler)();
00194 __result = realloc(__p, __n);
00195 if (__result)
00196 return(__result);
00197 }
00198 }
00199
00200
00201
00202 #ifdef __USE_MALLOC
00203 typedef __malloc_alloc_template<0> __mem_interface;
00204 #else
00205 typedef __new_alloc __mem_interface;
00206 #endif
00207
00208
00219 template<class _Tp, class _Alloc>
00220 class __simple_alloc
00221 {
00222 public:
00223 static _Tp* allocate(size_t __n)
00224 { return 0 == __n ? 0 : (_Tp*) _Alloc::allocate(__n * sizeof (_Tp)); }
00225
00226 static _Tp* allocate()
00227 { return (_Tp*) _Alloc::allocate(sizeof (_Tp)); }
00228
00229 static void deallocate(_Tp* __p, size_t __n)
00230 { if (0 != __n) _Alloc::deallocate(__p, __n * sizeof (_Tp)); }
00231
00232 static void deallocate(_Tp* __p)
00233 { _Alloc::deallocate(__p, sizeof (_Tp)); }
00234 };
00235
00236
00251 template <class _Alloc>
00252 class __debug_alloc
00253 {
00254 private:
00255 enum {_S_extra = 8};
00256
00257
00258 public:
00259
00260 static void* allocate(size_t __n)
00261 {
00262 char* __result = (char*)_Alloc::allocate(__n + (int) _S_extra);
00263 *(size_t*)__result = __n;
00264 return __result + (int) _S_extra;
00265 }
00266
00267 static void deallocate(void* __p, size_t __n)
00268 {
00269 char* __real_p = (char*)__p - (int) _S_extra;
00270 assert(*(size_t*)__real_p == __n);
00271 _Alloc::deallocate(__real_p, __n + (int) _S_extra);
00272 }
00273
00274 static void* reallocate(void* __p, size_t __old_sz, size_t __new_sz)
00275 {
00276 char* __real_p = (char*)__p - (int) _S_extra;
00277 assert(*(size_t*)__real_p == __old_sz);
00278 char* __result = (char*)
00279 _Alloc::reallocate(__real_p, __old_sz + (int) _S_extra,
00280 __new_sz + (int) _S_extra);
00281 *(size_t*)__result = __new_sz;
00282 return __result + (int) _S_extra;
00283 }
00284 };
00285
00286
00287 #ifdef __USE_MALLOC
00288
00289 typedef __mem_interface __alloc;
00290 typedef __mem_interface __single_client_alloc;
00291
00292 #else
00293
00294
00324 template<bool __threads, int __inst>
00325 class __default_alloc_template
00326 {
00327 private:
00328 enum {_ALIGN = 8};
00329 enum {_MAX_BYTES = 128};
00330 enum {_NFREELISTS = _MAX_BYTES / _ALIGN};
00331
00332 union _Obj
00333 {
00334 union _Obj* _M_free_list_link;
00335 char _M_client_data[1];
00336 };
00337
00338 static _Obj* volatile _S_free_list[_NFREELISTS];
00339
00340
00341 static char* _S_start_free;
00342 static char* _S_end_free;
00343 static size_t _S_heap_size;
00344
00345 static _STL_mutex_lock _S_node_allocator_lock;
00346
00347 static size_t
00348 _S_round_up(size_t __bytes)
00349 { return (((__bytes) + (size_t) _ALIGN-1) & ~((size_t) _ALIGN - 1)); }
00350
00351 static size_t
00352 _S_freelist_index(size_t __bytes)
00353 { return (((__bytes) + (size_t)_ALIGN-1)/(size_t)_ALIGN - 1); }
00354
00355
00356
00357 static void*
00358 _S_refill(size_t __n);
00359
00360
00361
00362 static char*
00363 _S_chunk_alloc(size_t __size, int& __nobjs);
00364
00365
00366
00367 class _Lock
00368 {
00369 public:
00370 _Lock() { if (__threads) _S_node_allocator_lock._M_acquire_lock(); }
00371 ~_Lock() { if (__threads) _S_node_allocator_lock._M_release_lock(); }
00372 } __attribute__ ((__unused__));
00373 friend class _Lock;
00374
00375 public:
00376
00377 static void*
00378 allocate(size_t __n)
00379 {
00380 void* __ret = 0;
00381
00382 if (__n > (size_t) _MAX_BYTES)
00383 __ret = __mem_interface::allocate(__n);
00384 else
00385 {
00386 _Obj* volatile* __my_free_list = _S_free_list
00387 + _S_freelist_index(__n);
00388
00389
00390
00391 _Lock __lock_instance;
00392 _Obj* __restrict__ __result = *__my_free_list;
00393 if (__result == 0)
00394 __ret = _S_refill(_S_round_up(__n));
00395 else
00396 {
00397 *__my_free_list = __result -> _M_free_list_link;
00398 __ret = __result;
00399 }
00400 }
00401 return __ret;
00402 };
00403
00404
00405 static void
00406 deallocate(void* __p, size_t __n)
00407 {
00408 if (__n > (size_t) _MAX_BYTES)
00409 __mem_interface::deallocate(__p, __n);
00410 else
00411 {
00412 _Obj* volatile* __my_free_list
00413 = _S_free_list + _S_freelist_index(__n);
00414 _Obj* __q = (_Obj*)__p;
00415
00416
00417
00418 _Lock __lock_instance;
00419 __q -> _M_free_list_link = *__my_free_list;
00420 *__my_free_list = __q;
00421 }
00422 }
00423
00424 static void*
00425 reallocate(void* __p, size_t __old_sz, size_t __new_sz);
00426 };
00427
00428
00429 template<bool __threads, int __inst>
00430 inline bool
00431 operator==(const __default_alloc_template<__threads, __inst>&,
00432 const __default_alloc_template<__threads, __inst>&)
00433 { return true; }
00434
00435 template<bool __threads, int __inst>
00436 inline bool
00437 operator!=(const __default_alloc_template<__threads, __inst>&,
00438 const __default_alloc_template<__threads, __inst>&)
00439 { return false; }
00440
00441
00442
00443
00444
00445 template<bool __threads, int __inst>
00446 char*
00447 __default_alloc_template<__threads, __inst>::_S_chunk_alloc(size_t __size,
00448 int& __nobjs)
00449 {
00450 char* __result;
00451 size_t __total_bytes = __size * __nobjs;
00452 size_t __bytes_left = _S_end_free - _S_start_free;
00453
00454 if (__bytes_left >= __total_bytes)
00455 {
00456 __result = _S_start_free;
00457 _S_start_free += __total_bytes;
00458 return(__result);
00459 }
00460 else if (__bytes_left >= __size)
00461 {
00462 __nobjs = (int)(__bytes_left/__size);
00463 __total_bytes = __size * __nobjs;
00464 __result = _S_start_free;
00465 _S_start_free += __total_bytes;
00466 return(__result);
00467 }
00468 else
00469 {
00470 size_t __bytes_to_get =
00471 2 * __total_bytes + _S_round_up(_S_heap_size >> 4);
00472
00473 if (__bytes_left > 0)
00474 {
00475 _Obj* volatile* __my_free_list =
00476 _S_free_list + _S_freelist_index(__bytes_left);
00477
00478 ((_Obj*)_S_start_free) -> _M_free_list_link = *__my_free_list;
00479 *__my_free_list = (_Obj*)_S_start_free;
00480 }
00481 _S_start_free = (char*) __mem_interface::allocate(__bytes_to_get);
00482 if (0 == _S_start_free)
00483 {
00484 size_t __i;
00485 _Obj* volatile* __my_free_list;
00486 _Obj* __p;
00487
00488
00489
00490 __i = __size;
00491 for (; __i <= (size_t) _MAX_BYTES; __i += (size_t) _ALIGN)
00492 {
00493 __my_free_list = _S_free_list + _S_freelist_index(__i);
00494 __p = *__my_free_list;
00495 if (0 != __p)
00496 {
00497 *__my_free_list = __p -> _M_free_list_link;
00498 _S_start_free = (char*)__p;
00499 _S_end_free = _S_start_free + __i;
00500 return(_S_chunk_alloc(__size, __nobjs));
00501
00502
00503 }
00504 }
00505 _S_end_free = 0;
00506 _S_start_free = (char*)__mem_interface::allocate(__bytes_to_get);
00507
00508
00509 }
00510 _S_heap_size += __bytes_to_get;
00511 _S_end_free = _S_start_free + __bytes_to_get;
00512 return(_S_chunk_alloc(__size, __nobjs));
00513 }
00514 }
00515
00516
00517
00518
00519
00520 template<bool __threads, int __inst>
00521 void*
00522 __default_alloc_template<__threads, __inst>::_S_refill(size_t __n)
00523 {
00524 int __nobjs = 20;
00525 char* __chunk = _S_chunk_alloc(__n, __nobjs);
00526 _Obj* volatile* __my_free_list;
00527 _Obj* __result;
00528 _Obj* __current_obj;
00529 _Obj* __next_obj;
00530 int __i;
00531
00532 if (1 == __nobjs) return(__chunk);
00533 __my_free_list = _S_free_list + _S_freelist_index(__n);
00534
00535
00536 __result = (_Obj*)__chunk;
00537 *__my_free_list = __next_obj = (_Obj*)(__chunk + __n);
00538 for (__i = 1; ; __i++) {
00539 __current_obj = __next_obj;
00540 __next_obj = (_Obj*)((char*)__next_obj + __n);
00541 if (__nobjs - 1 == __i) {
00542 __current_obj -> _M_free_list_link = 0;
00543 break;
00544 } else {
00545 __current_obj -> _M_free_list_link = __next_obj;
00546 }
00547 }
00548 return(__result);
00549 }
00550
00551
00552 template<bool threads, int inst>
00553 void*
00554 __default_alloc_template<threads, inst>::reallocate(void* __p,
00555 size_t __old_sz,
00556 size_t __new_sz)
00557 {
00558 void* __result;
00559 size_t __copy_sz;
00560
00561 if (__old_sz > (size_t) _MAX_BYTES && __new_sz > (size_t) _MAX_BYTES) {
00562 return(realloc(__p, __new_sz));
00563 }
00564 if (_S_round_up(__old_sz) == _S_round_up(__new_sz)) return(__p);
00565 __result = allocate(__new_sz);
00566 __copy_sz = __new_sz > __old_sz? __old_sz : __new_sz;
00567 memcpy(__result, __p, __copy_sz);
00568 deallocate(__p, __old_sz);
00569 return(__result);
00570 }
00571
00572 template<bool __threads, int __inst>
00573 _STL_mutex_lock
00574 __default_alloc_template<__threads, __inst>::_S_node_allocator_lock
00575 __STL_MUTEX_INITIALIZER;
00576
00577 template<bool __threads, int __inst>
00578 char* __default_alloc_template<__threads, __inst>::_S_start_free = 0;
00579
00580 template<bool __threads, int __inst>
00581 char* __default_alloc_template<__threads, __inst>::_S_end_free = 0;
00582
00583 template<bool __threads, int __inst>
00584 size_t __default_alloc_template<__threads, __inst>::_S_heap_size = 0;
00585
00586 template<bool __threads, int __inst>
00587 typename __default_alloc_template<__threads, __inst>::_Obj* volatile
00588 __default_alloc_template<__threads, __inst>::_S_free_list[_NFREELISTS];
00589
00590 typedef __default_alloc_template<true, 0> __alloc;
00591 typedef __default_alloc_template<false, 0> __single_client_alloc;
00592
00593
00594 #endif
00595
00596
00613 template <class _Tp>
00614 class allocator
00615 {
00616 typedef __alloc _Alloc;
00617 public:
00618 typedef size_t size_type;
00619 typedef ptrdiff_t difference_type;
00620 typedef _Tp* pointer;
00621 typedef const _Tp* const_pointer;
00622 typedef _Tp& reference;
00623 typedef const _Tp& const_reference;
00624 typedef _Tp value_type;
00625
00626 template <class _Tp1> struct rebind {
00627 typedef allocator<_Tp1> other;
00628 };
00629
00630 allocator() throw() {}
00631 allocator(const allocator&) throw() {}
00632 template <class _Tp1> allocator(const allocator<_Tp1>&) throw() {}
00633 ~allocator() throw() {}
00634
00635 pointer address(reference __x) const { return &__x; }
00636 const_pointer address(const_reference __x) const { return &__x; }
00637
00638
00639
00640 _Tp* allocate(size_type __n, const void* = 0) {
00641 return __n != 0 ? static_cast<_Tp*>(_Alloc::allocate(__n * sizeof(_Tp)))
00642 : 0;
00643 }
00644
00645
00646 void deallocate(pointer __p, size_type __n)
00647 { _Alloc::deallocate(__p, __n * sizeof(_Tp)); }
00648
00649 size_type max_size() const throw()
00650 { return size_t(-1) / sizeof(_Tp); }
00651
00652 void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
00653 void destroy(pointer __p) { __p->~_Tp(); }
00654 };
00655
00656 template<>
00657 class allocator<void> {
00658 public:
00659 typedef size_t size_type;
00660 typedef ptrdiff_t difference_type;
00661 typedef void* pointer;
00662 typedef const void* const_pointer;
00663 typedef void value_type;
00664
00665 template <class _Tp1> struct rebind {
00666 typedef allocator<_Tp1> other;
00667 };
00668 };
00669
00670
00671 template <class _T1, class _T2>
00672 inline bool operator==(const allocator<_T1>&, const allocator<_T2>&)
00673 {
00674 return true;
00675 }
00676
00677 template <class _T1, class _T2>
00678 inline bool operator!=(const allocator<_T1>&, const allocator<_T2>&)
00679 {
00680 return false;
00681 }
00682
00683
00695 template <class _Tp, class _Alloc>
00696 struct __allocator
00697 {
00698 _Alloc __underlying_alloc;
00699
00700 typedef size_t size_type;
00701 typedef ptrdiff_t difference_type;
00702 typedef _Tp* pointer;
00703 typedef const _Tp* const_pointer;
00704 typedef _Tp& reference;
00705 typedef const _Tp& const_reference;
00706 typedef _Tp value_type;
00707
00708 template <class _Tp1> struct rebind {
00709 typedef __allocator<_Tp1, _Alloc> other;
00710 };
00711
00712 __allocator() throw() {}
00713 __allocator(const __allocator& __a) throw()
00714 : __underlying_alloc(__a.__underlying_alloc) {}
00715 template <class _Tp1>
00716 __allocator(const __allocator<_Tp1, _Alloc>& __a) throw()
00717 : __underlying_alloc(__a.__underlying_alloc) {}
00718 ~__allocator() throw() {}
00719
00720 pointer address(reference __x) const { return &__x; }
00721 const_pointer address(const_reference __x) const { return &__x; }
00722
00723
00724 _Tp* allocate(size_type __n, const void* = 0) {
00725 return __n != 0
00726 ? static_cast<_Tp*>(__underlying_alloc.allocate(__n * sizeof(_Tp)))
00727 : 0;
00728 }
00729
00730
00731 void deallocate(pointer __p, size_type __n)
00732 { __underlying_alloc.deallocate(__p, __n * sizeof(_Tp)); }
00733
00734 size_type max_size() const throw()
00735 { return size_t(-1) / sizeof(_Tp); }
00736
00737 void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
00738 void destroy(pointer __p) { __p->~_Tp(); }
00739 };
00740
00741 template <class _Alloc>
00742 class __allocator<void, _Alloc> {
00743 typedef size_t size_type;
00744 typedef ptrdiff_t difference_type;
00745 typedef void* pointer;
00746 typedef const void* const_pointer;
00747 typedef void value_type;
00748
00749 template <class _Tp1> struct rebind {
00750 typedef __allocator<_Tp1, _Alloc> other;
00751 };
00752 };
00753
00754 template <class _Tp, class _Alloc>
00755 inline bool operator==(const __allocator<_Tp, _Alloc>& __a1,
00756 const __allocator<_Tp, _Alloc>& __a2)
00757 {
00758 return __a1.__underlying_alloc == __a2.__underlying_alloc;
00759 }
00760
00761 template <class _Tp, class _Alloc>
00762 inline bool operator!=(const __allocator<_Tp, _Alloc>& __a1,
00763 const __allocator<_Tp, _Alloc>& __a2)
00764 {
00765 return __a1.__underlying_alloc != __a2.__underlying_alloc;
00766 }
00767
00768
00770
00774 template <int inst>
00775 inline bool operator==(const __malloc_alloc_template<inst>&,
00776 const __malloc_alloc_template<inst>&)
00777 {
00778 return true;
00779 }
00780
00781 template <int __inst>
00782 inline bool operator!=(const __malloc_alloc_template<__inst>&,
00783 const __malloc_alloc_template<__inst>&)
00784 {
00785 return false;
00786 }
00787
00788 template <class _Alloc>
00789 inline bool operator==(const __debug_alloc<_Alloc>&,
00790 const __debug_alloc<_Alloc>&) {
00791 return true;
00792 }
00793
00794 template <class _Alloc>
00795 inline bool operator!=(const __debug_alloc<_Alloc>&,
00796 const __debug_alloc<_Alloc>&) {
00797 return false;
00798 }
00800
00801
00839
00840 template <class _Tp, class _Allocator>
00841 struct _Alloc_traits
00842 {
00843 static const bool _S_instanceless = false;
00844 typedef typename _Allocator::template rebind<_Tp>::other allocator_type;
00845 };
00846
00847 template <class _Tp, class _Allocator>
00848 const bool _Alloc_traits<_Tp, _Allocator>::_S_instanceless;
00849
00851 template <class _Tp, class _Tp1>
00852 struct _Alloc_traits<_Tp, allocator<_Tp1> >
00853 {
00854 static const bool _S_instanceless = true;
00855 typedef __simple_alloc<_Tp, __alloc> _Alloc_type;
00856 typedef allocator<_Tp> allocator_type;
00857 };
00859
00861
00862 template <class _Tp, int __inst>
00863 struct _Alloc_traits<_Tp, __malloc_alloc_template<__inst> >
00864 {
00865 static const bool _S_instanceless = true;
00866 typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
00867 typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
00868 };
00869
00870 #ifndef __USE_MALLOC
00871 template <class _Tp, bool __threads, int __inst>
00872 struct _Alloc_traits<_Tp, __default_alloc_template<__threads, __inst> >
00873 {
00874 static const bool _S_instanceless = true;
00875 typedef __simple_alloc<_Tp, __default_alloc_template<__threads, __inst> >
00876 _Alloc_type;
00877 typedef __allocator<_Tp, __default_alloc_template<__threads, __inst> >
00878 allocator_type;
00879 };
00880 #endif
00881
00882 template <class _Tp, class _Alloc>
00883 struct _Alloc_traits<_Tp, __debug_alloc<_Alloc> >
00884 {
00885 static const bool _S_instanceless = true;
00886 typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type;
00887 typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type;
00888 };
00890
00892
00893 template <class _Tp, class _Tp1, int __inst>
00894 struct _Alloc_traits<_Tp,
00895 __allocator<_Tp1, __malloc_alloc_template<__inst> > >
00896 {
00897 static const bool _S_instanceless = true;
00898 typedef __simple_alloc<_Tp, __malloc_alloc_template<__inst> > _Alloc_type;
00899 typedef __allocator<_Tp, __malloc_alloc_template<__inst> > allocator_type;
00900 };
00901
00902 #ifndef __USE_MALLOC
00903 template <class _Tp, class _Tp1, bool __thr, int __inst>
00904 struct _Alloc_traits<_Tp,
00905 __allocator<_Tp1,
00906 __default_alloc_template<__thr, __inst> > >
00907 {
00908 static const bool _S_instanceless = true;
00909 typedef __simple_alloc<_Tp, __default_alloc_template<__thr,__inst> >
00910 _Alloc_type;
00911 typedef __allocator<_Tp, __default_alloc_template<__thr,__inst> >
00912 allocator_type;
00913 };
00914 #endif
00915
00916 template <class _Tp, class _Tp1, class _Alloc>
00917 struct _Alloc_traits<_Tp, __allocator<_Tp1, __debug_alloc<_Alloc> > >
00918 {
00919 static const bool _S_instanceless = true;
00920 typedef __simple_alloc<_Tp, __debug_alloc<_Alloc> > _Alloc_type;
00921 typedef __allocator<_Tp, __debug_alloc<_Alloc> > allocator_type;
00922 };
00924
00925
00926
00927
00928 extern template class allocator<char>;
00929 extern template class allocator<wchar_t>;
00930 #ifdef __USE_MALLOC
00931 extern template class __malloc_alloc_template<0>;
00932 #else
00933 extern template class __default_alloc_template<true, 0>;
00934 #endif
00935 }
00936
00937 #endif
00938
00939
00940
00941