Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygen_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 _STLP_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 memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size); 00138 #endif 00139 return __ret; 00140 } 00141 else 00142 return 0; 00143 } 00144 00145 void deallocate(pointer __p, size_type __n) { 00146 _STLP_ASSERT( (__p == 0) == (__n == 0) ) 00147 if (__p != 0) { 00148 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC) 00149 memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type)); 00150 #endif 00151 _S_Alloc::deallocate(__p, __n * sizeof(value_type)); 00152 } 00153 } 00154 00155 size_type max_size() const _STLP_NOTHROW 00156 { return size_t(-1) / sizeof(_Tp); } 00157 00158 void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } 00159 void destroy(pointer _p) { _p->~_Tp(); } 00160 00161 #if defined (_STLP_NO_EXTENSIONS) 00162 /* STLport extension giving rounded size of an allocated memory buffer 00163 * This method do not have to be part of a user defined allocator implementation 00164 * and won't even be called if such a function was granted. 00165 */ 00166 protected: 00167 #endif 00168 _Tp* allocate(size_type __n, size_type& __allocated_n) { 00169 if (__n > max_size()) { 00170 _STLP_THROW_BAD_ALLOC; 00171 } 00172 if (__n != 0) { 00173 size_type __buf_size = __n * sizeof(value_type); 00174 _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size)); 00175 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC) 00176 memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size); 00177 #endif 00178 __allocated_n = __buf_size / sizeof(value_type); 00179 return __ret; 00180 } 00181 else 00182 return 0; 00183 } 00184 #if defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND) && !defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER) 00185 void _M_swap_workaround(pthread_allocator<_Tp>& __x) {} 00186 #endif 00187 }; 00188 00189 _STLP_TEMPLATE_NULL 00190 class _STLP_CLASS_DECLSPEC pthread_allocator<void> { 00191 public: 00192 typedef size_t size_type; 00193 typedef ptrdiff_t difference_type; 00194 typedef void* pointer; 00195 typedef const void* const_pointer; 00196 typedef void value_type; 00197 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES 00198 template <class _NewType> struct rebind { 00199 typedef pthread_allocator<_NewType> other; 00200 }; 00201 #endif 00202 }; 00203 00204 template <class _T1, class _T2> 00205 inline bool operator==(const pthread_allocator<_T1>&, 00206 const pthread_allocator<_T2>& a2) 00207 { return true; } 00208 00209 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER 00210 template <class _T1, class _T2> 00211 inline bool operator!=(const pthread_allocator<_T1>&, 00212 const pthread_allocator<_T2>&) 00213 { return false; } 00214 #endif 00215 00216 00217 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 00218 00219 template <class _Tp, class _Atype> 00220 struct _Alloc_traits<_Tp, pthread_allocator<_Atype> > 00221 { typedef pthread_allocator<_Tp> allocator_type; }; 00222 00223 #endif 00224 00225 #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) 00226 00227 template <class _Tp1, class _Tp2> 00228 inline pthread_allocator<_Tp2>& 00229 __stl_alloc_rebind(pthread_allocator<_Tp1>& __x, const _Tp2*) 00230 { return (pthread_allocator<_Tp2>&)__x; } 00231 00232 template <class _Tp1, class _Tp2> 00233 inline pthread_allocator<_Tp2> 00234 __stl_alloc_create(pthread_allocator<_Tp1>&, const _Tp2*) 00235 { return pthread_allocator<_Tp2>(); } 00236 00237 #endif 00238 00239 _STLP_MOVE_TO_PRIV_NAMESPACE 00240 00241 template <class _Tp> 00242 struct __pthread_alloc_type_traits { 00243 typedef typename _IsSTLportClass<pthread_allocator<_Tp> >::_Ret _STLportAlloc; 00244 //The default allocator implementation which is recognize thanks to the 00245 //__stlport_class inheritance is a stateless object so: 00246 typedef _STLportAlloc has_trivial_default_constructor; 00247 typedef _STLportAlloc has_trivial_copy_constructor; 00248 typedef _STLportAlloc has_trivial_assignment_operator; 00249 typedef _STLportAlloc has_trivial_destructor; 00250 typedef _STLportAlloc is_POD_type; 00251 }; 00252 00253 _STLP_MOVE_TO_STD_NAMESPACE 00254 00255 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 00256 template <class _Tp> 00257 struct __type_traits<pthread_allocator<_Tp> > : _STLP_PRIV __pthread_alloc_type_traits<_Tp> {}; 00258 #else 00259 _STLP_TEMPLATE_NULL 00260 struct __type_traits<pthread_allocator<char> > : _STLP_PRIV __pthread_alloc_type_traits<char> {}; 00261 # if defined (_STLP_HAS_WCHAR_T) 00262 _STLP_TEMPLATE_NULL 00263 struct __type_traits<pthread_allocator<wchar_t> > : _STLP_PRIV __pthread_alloc_type_traits<wchar_t> {}; 00264 # endif 00265 # if defined (_STLP_USE_PTR_SPECIALIZATIONS) 00266 _STLP_TEMPLATE_NULL 00267 struct __type_traits<pthread_allocator<void*> > : _STLP_PRIV __pthread_alloc_type_traits<void*> {}; 00268 # endif 00269 #endif 00270 00271 // 00272 // per_thread_allocator<> : this allocator always return memory to the same thread 00273 // it was allocated from. 00274 // 00275 00276 template <class _Tp> 00277 class per_thread_allocator { 00278 typedef pthread_alloc _S_Alloc; // The underlying allocator. 00279 typedef pthread_alloc::__state_type __state_type; 00280 public: 00281 typedef size_t size_type; 00282 typedef ptrdiff_t difference_type; 00283 typedef _Tp* pointer; 00284 typedef const _Tp* const_pointer; 00285 typedef _Tp& reference; 00286 typedef const _Tp& const_reference; 00287 typedef _Tp value_type; 00288 00289 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES 00290 template <class _NewType> struct rebind { 00291 typedef per_thread_allocator<_NewType> other; 00292 }; 00293 #endif 00294 00295 per_thread_allocator() _STLP_NOTHROW { 00296 _M_state = _S_Alloc::_S_get_per_thread_state(); 00297 } 00298 per_thread_allocator(const per_thread_allocator<_Tp>& __a) _STLP_NOTHROW : _M_state(__a._M_state){} 00299 00300 #if defined (_STLP_MEMBER_TEMPLATES) /* && defined (_STLP_FUNCTION_PARTIAL_ORDER) */ 00301 template <class _OtherType> per_thread_allocator(const per_thread_allocator<_OtherType>& __a) 00302 _STLP_NOTHROW : _M_state(__a._M_state) {} 00303 #endif 00304 00305 ~per_thread_allocator() _STLP_NOTHROW {} 00306 00307 pointer address(reference __x) const { return &__x; } 00308 const_pointer address(const_reference __x) const { return &__x; } 00309 00310 // __n is permitted to be 0. The C++ standard says nothing about what 00311 // the return value is when __n == 0. 00312 _Tp* allocate(size_type __n, const void* = 0) { 00313 if (__n > max_size()) { 00314 _STLP_THROW_BAD_ALLOC; 00315 } 00316 if (__n != 0) { 00317 size_type __buf_size = __n * sizeof(value_type); 00318 _Tp* __ret = __REINTERPRET_CAST(_Tp*, _S_Alloc::allocate(__buf_size, _M_state)); 00319 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC) 00320 memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size); 00321 #endif 00322 return __ret; 00323 } 00324 else 00325 return 0; 00326 } 00327 00328 void deallocate(pointer __p, size_type __n) { 00329 _STLP_ASSERT( (__p == 0) == (__n == 0) ) 00330 if (__p != 0) { 00331 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC) 00332 memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type)); 00333 #endif 00334 _S_Alloc::deallocate(__p, __n * sizeof(value_type), _M_state); 00335 } 00336 } 00337 00338 size_type max_size() const _STLP_NOTHROW 00339 { return size_t(-1) / sizeof(_Tp); } 00340 00341 void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); } 00342 void destroy(pointer _p) { _p->~_Tp(); } 00343 00344 // state is being kept here 00345 __state_type* _M_state; 00346 00347 #if defined (_STLP_NO_EXTENSIONS) 00348 /* STLport extension giving rounded size of an allocated memory buffer 00349 * This method do not have to be part of a user defined allocator implementation 00350 * and won't even be called if such a function was granted. 00351 */ 00352 protected: 00353 #endif 00354 _Tp* allocate(size_type __n, size_type& __allocated_n) { 00355 if (__n > max_size()) { 00356 _STLP_THROW_BAD_ALLOC; 00357 } 00358 if (__n != 0) { 00359 size_type __buf_size = __n * sizeof(value_type); 00360 _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size, _M_state)); 00361 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC) 00362 memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size); 00363 #endif 00364 __allocated_n = __buf_size / sizeof(value_type); 00365 return __ret; 00366 } 00367 else 00368 return 0; 00369 } 00370 }; 00371 00372 _STLP_TEMPLATE_NULL 00373 class _STLP_CLASS_DECLSPEC per_thread_allocator<void> { 00374 public: 00375 typedef size_t size_type; 00376 typedef ptrdiff_t difference_type; 00377 typedef void* pointer; 00378 typedef const void* const_pointer; 00379 typedef void value_type; 00380 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES 00381 template <class _NewType> struct rebind { 00382 typedef per_thread_allocator<_NewType> other; 00383 }; 00384 #endif 00385 }; 00386 00387 template <class _T1, class _T2> 00388 inline bool operator==(const per_thread_allocator<_T1>& __a1, 00389 const per_thread_allocator<_T2>& __a2) 00390 { return __a1._M_state == __a2._M_state; } 00391 00392 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER 00393 template <class _T1, class _T2> 00394 inline bool operator!=(const per_thread_allocator<_T1>& __a1, 00395 const per_thread_allocator<_T2>& __a2) 00396 { return __a1._M_state != __a2._M_state; } 00397 #endif 00398 00399 00400 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 00401 00402 template <class _Tp, class _Atype> 00403 struct _Alloc_traits<_Tp, per_thread_allocator<_Atype> > 00404 { typedef per_thread_allocator<_Tp> allocator_type; }; 00405 00406 #endif 00407 00408 #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE) 00409 00410 template <class _Tp1, class _Tp2> 00411 inline per_thread_allocator<_Tp2>& 00412 __stl_alloc_rebind(per_thread_allocator<_Tp1>& __x, const _Tp2*) 00413 { return (per_thread_allocator<_Tp2>&)__x; } 00414 00415 template <class _Tp1, class _Tp2> 00416 inline per_thread_allocator<_Tp2> 00417 __stl_alloc_create(per_thread_allocator<_Tp1>&, const _Tp2*) 00418 { return per_thread_allocator<_Tp2>(); } 00419 00420 #endif /* _STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE */ 00421 00422 _STLP_MOVE_TO_PRIV_NAMESPACE 00423 00424 template <class _Tp> 00425 struct __perthread_alloc_type_traits { 00426 typedef typename _IsSTLportClass<per_thread_allocator<_Tp> >::_Ret _STLportAlloc; 00427 //The default allocator implementation which is recognize thanks to the 00428 //__stlport_class inheritance is a stateless object so: 00429 typedef __false_type has_trivial_default_constructor; 00430 typedef _STLportAlloc has_trivial_copy_constructor; 00431 typedef _STLportAlloc has_trivial_assignment_operator; 00432 typedef _STLportAlloc has_trivial_destructor; 00433 typedef __false_type is_POD_type; 00434 }; 00435 00436 _STLP_MOVE_TO_STD_NAMESPACE 00437 00438 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION) 00439 template <class _Tp> 00440 struct __type_traits<per_thread_allocator<_Tp> > : _STLP_PRIV __perthread_alloc_type_traits<_Tp> {}; 00441 #else 00442 _STLP_TEMPLATE_NULL 00443 struct __type_traits<per_thread_allocator<char> > : _STLP_PRIV __perthread_alloc_type_traits<char> {}; 00444 # if defined (_STLP_HAS_WCHAR_T) 00445 _STLP_TEMPLATE_NULL 00446 struct __type_traits<per_thread_allocator<wchar_t> > : _STLP_PRIV __perthread_alloc_type_traits<wchar_t> {}; 00447 # endif 00448 # if defined (_STLP_USE_PTR_SPECIALIZATIONS) 00449 _STLP_TEMPLATE_NULL 00450 struct __type_traits<per_thread_allocator<void*> > : _STLP_PRIV __perthread_alloc_type_traits<void*> {}; 00451 # endif 00452 #endif 00453 00454 00455 _STLP_END_NAMESPACE 00456 00457 #endif /* _STLP_PTHREAD_ALLOC */ 00458 00459 // Local Variables: 00460 // mode:C++ 00461 // End: Generated on Fri May 25 2012 04:27:53 for ReactOS by
1.7.6.1
|