/home/ntakagi/work/STLport-5.1.5/stlport/stl/_pthread_alloc.h

Go to the documentation of this file.
00001 /*
00002  *
00003  * Copyright (c) 1994
00004  * Hewlett-Packard Company
00005  *
00006  * Copyright (c) 1996,1997
00007  * Silicon Graphics Computer Systems, Inc.
00008  *
00009  * Copyright (c) 1997
00010  * Moscow Center for SPARC Technology
00011  *
00012  * Copyright (c) 1999
00013  * Boris Fomitchev
00014  *
00015  * This material is provided "as is", with absolutely no warranty expressed
00016  * or implied. Any use is at your own risk.
00017  *
00018  * Permission to use or copy this software for any purpose is hereby granted
00019  * without fee, provided the above notices are retained on all copies.
00020  * Permission to modify the code and to distribute modified code is granted,
00021  * provided the above notices are retained, and a notice that the code was
00022  * modified is included with the above copyright notice.
00023  *
00024  */
00025 
00026 #ifndef _STLP_PTHREAD_ALLOC_H
00027 #define _STLP_PTHREAD_ALLOC_H
00028 
00029 /*
00030  * Pthread-specific node allocator.
00031  * This is similar to the default allocator, except that free-list
00032  * information is kept separately for each thread, avoiding locking.
00033  * This should be reasonably fast even in the presence of threads.
00034  * The down side is that storage may not be well-utilized.
00035  * It is not an error to allocate memory in thread A and deallocate
00036  * it in thread B.  But this effectively transfers ownership of the memory,
00037  * so that it can only be reallocated by thread B.  Thus this can effectively
00038  * result in a storage leak if it's done on a regular basis.
00039  * It can also result in frequent sharing of
00040  * cache lines among processors, with potentially serious performance
00041  * consequences.
00042  */
00043 
00044 #if !defined (_STLP_PTHREADS)
00045 #  error POSIX specific allocator implementation. Your system do not seems to \
00046 have this interface so please comment the _STLP_USE_PERTHREAD_ALLOC macro \
00047 or report to the STLport forum.
00048 #endif
00049 
00050 #if defined (_STLP_USE_NO_IOSTREAMS)
00051 #  error You cannot use per thread allocator implementation without building \
00052 STLport libraries.
00053 #endif
00054 
00055 #ifndef _STLP_INTERNAL_ALLOC_H
00056 #  include <stl/_alloc.h>
00057 #endif
00058 
00059 _STLP_BEGIN_NAMESPACE
00060 
00061 _STLP_MOVE_TO_PRIV_NAMESPACE
00062 
00063 struct _Pthread_alloc_per_thread_state;
00064 
00065 // Pthread-specific allocator.
00066 class _STLP_CLASS_DECLSPEC _Pthread_alloc {
00067 public: // but only for internal use:
00068   typedef _Pthread_alloc_per_thread_state __state_type;
00069   typedef char value_type;
00070 
00071 public:
00072   // Return a recycled or new per thread state.
00073   static __state_type * _STLP_CALL _S_get_per_thread_state();
00074 
00075   /* n must be > 0      */
00076   static void * _STLP_CALL allocate(size_t& __n);
00077 
00078   /* p may not be 0 */
00079   static void _STLP_CALL deallocate(void *__p, size_t __n);
00080 
00081   // boris : versions for per_thread_allocator
00082   /* n must be > 0      */
00083   static void * _STLP_CALL allocate(size_t& __n, __state_type* __a);
00084 
00085   /* p may not be 0 */
00086   static void _STLP_CALL deallocate(void *__p, size_t __n, __state_type* __a);
00087 
00088   static void * _STLP_CALL reallocate(void *__p, size_t __old_sz, size_t& __new_sz);
00089 };
00090 
00091 _STLP_MOVE_TO_STD_NAMESPACE
00092 
00093 typedef _STLP_PRIV _Pthread_alloc __pthread_alloc;
00094 typedef __pthread_alloc pthread_alloc;
00095 
00096 template <class _Tp>
00097 class pthread_allocator : public __stlport_class<pthread_allocator<_Tp> > {
00098   typedef pthread_alloc _S_Alloc;          // The underlying allocator.
00099 public:
00100   typedef size_t     size_type;
00101   typedef ptrdiff_t  difference_type;
00102   typedef _Tp*       pointer;
00103   typedef const _Tp* const_pointer;
00104   typedef _Tp&       reference;
00105   typedef const _Tp& const_reference;
00106   typedef _Tp        value_type;
00107 
00108 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
00109   template <class _NewType> struct rebind {
00110     typedef pthread_allocator<_NewType> other;
00111   };
00112 #endif
00113 
00114   pthread_allocator() _STLP_NOTHROW {}
00115   pthread_allocator(const pthread_allocator<_Tp>& a) _STLP_NOTHROW {}
00116 
00117 #if defined (_STLP_MEMBER_TEMPLATES) /* && defined (_STLP_FUNCTION_PARTIAL_ORDER) */
00118   template <class _OtherType> pthread_allocator(const pthread_allocator<_OtherType>&)
00119     _STLP_NOTHROW {}
00120 #endif
00121 
00122   ~pthread_allocator() _STLP_NOTHROW {}
00123 
00124   pointer address(reference __x) const { return &__x; }
00125   const_pointer address(const_reference __x) const { return &__x; }
00126 
00127   // __n is permitted to be 0.  The C++ standard says nothing about what
00128   // the return value is when __n == 0.
00129   _Tp* allocate(size_type __n, const void* = 0) {
00130     if (__n > max_size()) {
00131       __THROW_BAD_ALLOC;
00132     }
00133     if (__n != 0) {
00134       size_type __buf_size = __n * sizeof(value_type);
00135       _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size));
00136 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
00137       if (__ret != 0) {
00138         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
00139       }
00140 #endif
00141       return __ret;
00142     }
00143     else
00144       return 0;
00145   }
00146 
00147   void deallocate(pointer __p, size_type __n) {
00148     _STLP_ASSERT( (__p == 0) == (__n == 0) )
00149     if (__p != 0) {
00150 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
00151       memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type));
00152 #endif
00153       _S_Alloc::deallocate(__p, __n * sizeof(value_type));
00154     }
00155   }
00156 
00157   size_type max_size() const _STLP_NOTHROW
00158   { return size_t(-1) / sizeof(_Tp); }
00159 
00160   void construct(pointer __p, const _Tp& __val) { _STLP_PLACEMENT_NEW (__p) _Tp(__val); }
00161   void destroy(pointer _p) { _p->~_Tp(); }
00162 
00163 #if defined (_STLP_NO_EXTENSIONS)
00164   /* STLport extension giving rounded size of an allocated memory buffer
00165    * This method do not have to be part of a user defined allocator implementation
00166    * and won't even be called if such a function was granted.
00167    */
00168 protected:
00169 #endif
00170   _Tp* allocate(size_type __n, size_type& __allocated_n) {
00171     if (__n > max_size()) {
00172       __THROW_BAD_ALLOC;
00173     }
00174     if (__n != 0) {
00175       size_type __buf_size = __n * sizeof(value_type);
00176       _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size));
00177 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
00178       if (__ret != 0) {
00179         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
00180       }
00181 #endif
00182       __allocated_n = __buf_size / sizeof(value_type);
00183       return __ret;
00184     }
00185     else
00186       return 0;
00187   }
00188 };
00189 
00190 _STLP_TEMPLATE_NULL
00191 class _STLP_CLASS_DECLSPEC pthread_allocator<void> {
00192 public:
00193   typedef size_t      size_type;
00194   typedef ptrdiff_t   difference_type;
00195   typedef void*       pointer;
00196   typedef const void* const_pointer;
00197   typedef void        value_type;
00198 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
00199   template <class _NewType> struct rebind {
00200     typedef pthread_allocator<_NewType> other;
00201   };
00202 #endif
00203 };
00204 
00205 template <class _T1, class _T2>
00206 inline bool operator==(const pthread_allocator<_T1>&,
00207                        const pthread_allocator<_T2>& a2)
00208 { return true; }
00209 
00210 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER
00211 template <class _T1, class _T2>
00212 inline bool operator!=(const pthread_allocator<_T1>&,
00213                        const pthread_allocator<_T2>&)
00214 { return false; }
00215 #endif
00216 
00217 
00218 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
00219 
00220 #  if defined (_STLP_USE_RAW_SGI_ALLOCATORS)
00221 template <class _Tp>
00222 struct _Alloc_traits<_Tp, _Pthread_alloc>
00223 { typedef __allocator<_Tp, _Pthread_alloc> allocator_type; };
00224 #  endif
00225 
00226 template <class _Tp, class _Atype>
00227 struct _Alloc_traits<_Tp, pthread_allocator<_Atype> >
00228 { typedef pthread_allocator<_Tp> allocator_type; };
00229 
00230 #endif
00231 
00232 #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE)
00233 
00234 template <class _Tp1, class _Tp2>
00235 inline pthread_allocator<_Tp2>&
00236 __stl_alloc_rebind(pthread_allocator<_Tp1>& __x, const _Tp2*)
00237 { return (pthread_allocator<_Tp2>&)__x; }
00238 
00239 template <class _Tp1, class _Tp2>
00240 inline pthread_allocator<_Tp2>
00241 __stl_alloc_create(pthread_allocator<_Tp1>&, const _Tp2*)
00242 { return pthread_allocator<_Tp2>(); }
00243 
00244 #endif
00245 
00246 _STLP_MOVE_TO_PRIV_NAMESPACE
00247 
00248 template <class _Tp>
00249 struct __pthread_alloc_type_traits {
00250   typedef typename _IsSTLportClass<pthread_allocator<_Tp> >::_Ret _STLportAlloc;
00251   //The default allocator implementation which is recognize thanks to the
00252   //__stlport_class inheritance is a stateless object so:
00253   typedef _STLportAlloc has_trivial_default_constructor;
00254   typedef _STLportAlloc has_trivial_copy_constructor;
00255   typedef _STLportAlloc has_trivial_assignment_operator;
00256   typedef _STLportAlloc has_trivial_destructor;
00257   typedef _STLportAlloc is_POD_type;
00258 };
00259 
00260 _STLP_MOVE_TO_STD_NAMESPACE
00261 
00262 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
00263 template <class _Tp>
00264 struct __type_traits<pthread_allocator<_Tp> > : _STLP_PRIV __pthread_alloc_type_traits<_Tp> {};
00265 #else
00266 _STLP_TEMPLATE_NULL
00267 struct __type_traits<pthread_allocator<char> > : _STLP_PRIV __pthread_alloc_type_traits<char> {};
00268 #  if defined (_STLP_HAS_WCHAR_T)
00269 _STLP_TEMPLATE_NULL
00270 struct __type_traits<pthread_allocator<wchar_t> > : _STLP_PRIV __pthread_alloc_type_traits<wchar_t> {};
00271 #  endif
00272 #  if defined (_STLP_USE_PTR_SPECIALIZATIONS)
00273 _STLP_TEMPLATE_NULL
00274 struct __type_traits<pthread_allocator<void*> > : _STLP_PRIV __pthread_alloc_type_traits<void*> {};
00275 #  endif
00276 #endif
00277 
00278 //
00279 // per_thread_allocator<> : this allocator always return memory to the same thread
00280 // it was allocated from.
00281 //
00282 
00283 template <class _Tp>
00284 class per_thread_allocator {
00285   typedef pthread_alloc _S_Alloc;          // The underlying allocator.
00286   typedef pthread_alloc::__state_type __state_type;
00287 public:
00288   typedef size_t     size_type;
00289   typedef ptrdiff_t  difference_type;
00290   typedef _Tp*       pointer;
00291   typedef const _Tp* const_pointer;
00292   typedef _Tp&       reference;
00293   typedef const _Tp& const_reference;
00294   typedef _Tp        value_type;
00295 
00296 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
00297   template <class _NewType> struct rebind {
00298     typedef per_thread_allocator<_NewType> other;
00299   };
00300 #endif
00301 
00302   per_thread_allocator() _STLP_NOTHROW {
00303     _M_state = _S_Alloc::_S_get_per_thread_state();
00304   }
00305   per_thread_allocator(const per_thread_allocator<_Tp>& __a) _STLP_NOTHROW : _M_state(__a._M_state){}
00306 
00307 #if defined (_STLP_MEMBER_TEMPLATES) /* && defined (_STLP_FUNCTION_PARTIAL_ORDER) */
00308   template <class _OtherType> per_thread_allocator(const per_thread_allocator<_OtherType>& __a)
00309     _STLP_NOTHROW : _M_state(__a._M_state) {}
00310 #endif
00311 
00312   ~per_thread_allocator() _STLP_NOTHROW {}
00313 
00314   pointer address(reference __x) const { return &__x; }
00315   const_pointer address(const_reference __x) const { return &__x; }
00316 
00317   // __n is permitted to be 0.  The C++ standard says nothing about what
00318   // the return value is when __n == 0.
00319   _Tp* allocate(size_type __n, const void* = 0) {
00320     if (__n > max_size()) {
00321       __THROW_BAD_ALLOC;
00322     }
00323     if (__n != 0) {
00324       size_type __buf_size = __n * sizeof(value_type);
00325       _Tp* __ret = __REINTERPRET_CAST(_Tp*, _S_Alloc::allocate(__buf_size, _M_state));
00326 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
00327       if (__ret != 0) {
00328         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
00329       }
00330 #endif
00331       return __ret;
00332     }
00333     else
00334       return 0;
00335   }
00336 
00337   void deallocate(pointer __p, size_type __n) {
00338     _STLP_ASSERT( (__p == 0) == (__n == 0) )
00339     if (__p != 0) {
00340 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
00341       memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type));
00342 #endif
00343       _S_Alloc::deallocate(__p, __n * sizeof(value_type), _M_state);
00344     }
00345   }
00346 
00347   size_type max_size() const _STLP_NOTHROW
00348   { return size_t(-1) / sizeof(_Tp); }
00349 
00350   void construct(pointer __p, const _Tp& __val) { _STLP_PLACEMENT_NEW (__p) _Tp(__val); }
00351   void destroy(pointer _p) { _p->~_Tp(); }
00352 
00353   // state is being kept here
00354   __state_type* _M_state;
00355 
00356 #if defined (_STLP_NO_EXTENSIONS)
00357   /* STLport extension giving rounded size of an allocated memory buffer
00358    * This method do not have to be part of a user defined allocator implementation
00359    * and won't even be called if such a function was granted.
00360    */
00361 protected:
00362 #endif
00363   _Tp* allocate(size_type __n, size_type& __allocated_n) {
00364     if (__n > max_size()) {
00365       __THROW_BAD_ALLOC;
00366     }
00367     if (__n != 0) {
00368       size_type __buf_size = __n * sizeof(value_type);
00369       _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size, _M_state));
00370 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
00371       if (__ret != 0) {
00372         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
00373       }
00374 #endif
00375       __allocated_n = __buf_size / sizeof(value_type);
00376       return __ret;
00377     }
00378     else
00379       return 0;
00380   }
00381 };
00382 
00383 _STLP_TEMPLATE_NULL
00384 class _STLP_CLASS_DECLSPEC per_thread_allocator<void> {
00385 public:
00386   typedef size_t      size_type;
00387   typedef ptrdiff_t   difference_type;
00388   typedef void*       pointer;
00389   typedef const void* const_pointer;
00390   typedef void        value_type;
00391 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
00392   template <class _NewType> struct rebind {
00393     typedef per_thread_allocator<_NewType> other;
00394   };
00395 #endif
00396 };
00397 
00398 template <class _T1, class _T2>
00399 inline bool operator==(const per_thread_allocator<_T1>& __a1,
00400                        const per_thread_allocator<_T2>& __a2)
00401 { return __a1._M_state == __a2._M_state; }
00402 
00403 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER
00404 template <class _T1, class _T2>
00405 inline bool operator!=(const per_thread_allocator<_T1>& __a1,
00406                        const per_thread_allocator<_T2>& __a2)
00407 { return __a1._M_state != __a2._M_state; }
00408 #endif
00409 
00410 
00411 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
00412 
00413 template <class _Tp, class _Atype>
00414 struct _Alloc_traits<_Tp, per_thread_allocator<_Atype> >
00415 { typedef per_thread_allocator<_Tp> allocator_type; };
00416 
00417 #endif
00418 
00419 #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE)
00420 
00421 template <class _Tp1, class _Tp2>
00422 inline per_thread_allocator<_Tp2>&
00423 __stl_alloc_rebind(per_thread_allocator<_Tp1>& __x, const _Tp2*)
00424 { return (per_thread_allocator<_Tp2>&)__x; }
00425 
00426 template <class _Tp1, class _Tp2>
00427 inline per_thread_allocator<_Tp2>
00428 __stl_alloc_create(per_thread_allocator<_Tp1>&, const _Tp2*)
00429 { return per_thread_allocator<_Tp2>(); }
00430 
00431 #endif /* _STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE */
00432 
00433 _STLP_MOVE_TO_PRIV_NAMESPACE
00434 
00435 template <class _Tp>
00436 struct __perthread_alloc_type_traits {
00437   typedef typename _IsSTLportClass<per_thread_allocator<_Tp> >::_Ret _STLportAlloc;
00438   //The default allocator implementation which is recognize thanks to the
00439   //__stlport_class inheritance is a stateless object so:
00440   typedef __false_type has_trivial_default_constructor;
00441   typedef _STLportAlloc has_trivial_copy_constructor;
00442   typedef _STLportAlloc has_trivial_assignment_operator;
00443   typedef _STLportAlloc has_trivial_destructor;
00444   typedef __false_type is_POD_type;
00445 };
00446 
00447 _STLP_MOVE_TO_STD_NAMESPACE
00448 
00449 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
00450 template <class _Tp>
00451 struct __type_traits<per_thread_allocator<_Tp> > : _STLP_PRIV __perthread_alloc_type_traits<_Tp> {};
00452 #else
00453 _STLP_TEMPLATE_NULL
00454 struct __type_traits<per_thread_allocator<char> > : _STLP_PRIV __perthread_alloc_type_traits<char> {};
00455 #  if defined (_STLP_HAS_WCHAR_T)
00456 _STLP_TEMPLATE_NULL
00457 struct __type_traits<per_thread_allocator<wchar_t> > : _STLP_PRIV __perthread_alloc_type_traits<wchar_t> {};
00458 #  endif
00459 #  if defined (_STLP_USE_PTR_SPECIALIZATIONS)
00460 _STLP_TEMPLATE_NULL
00461 struct __type_traits<per_thread_allocator<void*> > : _STLP_PRIV __perthread_alloc_type_traits<void*> {};
00462 #  endif
00463 #endif
00464 
00465 
00466 _STLP_END_NAMESPACE
00467 
00468 #endif /* _STLP_PTHREAD_ALLOC */
00469 
00470 // Local Variables:
00471 // mode:C++
00472 // End:



Generated on Mon Mar 10 15:32:32 2008 by  doxygen 1.5.1