/home/ntakagi/work/STLport-5.1.5/stlport/stl/_pthread_alloc.hGo 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 ![]() |