_pthread_alloc.h 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461
  1. /*
  2. *
  3. * Copyright (c) 1994
  4. * Hewlett-Packard Company
  5. *
  6. * Copyright (c) 1996,1997
  7. * Silicon Graphics Computer Systems, Inc.
  8. *
  9. * Copyright (c) 1997
  10. * Moscow Center for SPARC Technology
  11. *
  12. * Copyright (c) 1999
  13. * Boris Fomitchev
  14. *
  15. * This material is provided "as is", with absolutely no warranty expressed
  16. * or implied. Any use is at your own risk.
  17. *
  18. * Permission to use or copy this software for any purpose is hereby granted
  19. * without fee, provided the above notices are retained on all copies.
  20. * Permission to modify the code and to distribute modified code is granted,
  21. * provided the above notices are retained, and a notice that the code was
  22. * modified is included with the above copyright notice.
  23. *
  24. */
  25. #ifndef _STLP_PTHREAD_ALLOC_H
  26. #define _STLP_PTHREAD_ALLOC_H
  27. /*
  28. * Pthread-specific node allocator.
  29. * This is similar to the default allocator, except that free-list
  30. * information is kept separately for each thread, avoiding locking.
  31. * This should be reasonably fast even in the presence of threads.
  32. * The down side is that storage may not be well-utilized.
  33. * It is not an error to allocate memory in thread A and deallocate
  34. * it in thread B. But this effectively transfers ownership of the memory,
  35. * so that it can only be reallocated by thread B. Thus this can effectively
  36. * result in a storage leak if it's done on a regular basis.
  37. * It can also result in frequent sharing of
  38. * cache lines among processors, with potentially serious performance
  39. * consequences.
  40. */
  41. #if !defined (_STLP_PTHREADS)
  42. # error POSIX specific allocator implementation. Your system do not seems to \
  43. have this interface so please comment the _STLP_USE_PERTHREAD_ALLOC macro \
  44. or report to the STLport forum.
  45. #endif
  46. #if defined (_STLP_USE_NO_IOSTREAMS)
  47. # error You cannot use per thread allocator implementation without building \
  48. STLport libraries.
  49. #endif
  50. #ifndef _STLP_INTERNAL_ALLOC_H
  51. # include <stl/_alloc.h>
  52. #endif
  53. _STLP_BEGIN_NAMESPACE
  54. _STLP_MOVE_TO_PRIV_NAMESPACE
  55. struct _Pthread_alloc_per_thread_state;
  56. // Pthread-specific allocator.
  57. class _STLP_CLASS_DECLSPEC _Pthread_alloc {
  58. public: // but only for internal use:
  59. typedef _Pthread_alloc_per_thread_state __state_type;
  60. typedef char value_type;
  61. public:
  62. // Return a recycled or new per thread state.
  63. static __state_type * _STLP_CALL _S_get_per_thread_state();
  64. /* n must be > 0 */
  65. static void * _STLP_CALL allocate(size_t& __n);
  66. /* p may not be 0 */
  67. static void _STLP_CALL deallocate(void *__p, size_t __n);
  68. // boris : versions for per_thread_allocator
  69. /* n must be > 0 */
  70. static void * _STLP_CALL allocate(size_t& __n, __state_type* __a);
  71. /* p may not be 0 */
  72. static void _STLP_CALL deallocate(void *__p, size_t __n, __state_type* __a);
  73. static void * _STLP_CALL reallocate(void *__p, size_t __old_sz, size_t& __new_sz);
  74. };
  75. _STLP_MOVE_TO_STD_NAMESPACE
  76. typedef _STLP_PRIV _Pthread_alloc __pthread_alloc;
  77. typedef __pthread_alloc pthread_alloc;
  78. template <class _Tp>
  79. class pthread_allocator : public __stlport_class<pthread_allocator<_Tp> > {
  80. typedef pthread_alloc _S_Alloc; // The underlying allocator.
  81. public:
  82. typedef size_t size_type;
  83. typedef ptrdiff_t difference_type;
  84. typedef _Tp* pointer;
  85. typedef const _Tp* const_pointer;
  86. typedef _Tp& reference;
  87. typedef const _Tp& const_reference;
  88. typedef _Tp value_type;
  89. #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
  90. template <class _NewType> struct rebind {
  91. typedef pthread_allocator<_NewType> other;
  92. };
  93. #endif
  94. pthread_allocator() _STLP_NOTHROW {}
  95. pthread_allocator(const pthread_allocator<_Tp>& a) _STLP_NOTHROW {}
  96. #if defined (_STLP_MEMBER_TEMPLATES) /* && defined (_STLP_FUNCTION_PARTIAL_ORDER) */
  97. template <class _OtherType> pthread_allocator(const pthread_allocator<_OtherType>&)
  98. _STLP_NOTHROW {}
  99. #endif
  100. ~pthread_allocator() _STLP_NOTHROW {}
  101. pointer address(reference __x) const { return &__x; }
  102. const_pointer address(const_reference __x) const { return &__x; }
  103. // __n is permitted to be 0. The C++ standard says nothing about what
  104. // the return value is when __n == 0.
  105. _Tp* allocate(size_type __n, const void* = 0) {
  106. if (__n > max_size()) {
  107. _STLP_THROW_BAD_ALLOC;
  108. }
  109. if (__n != 0) {
  110. size_type __buf_size = __n * sizeof(value_type);
  111. _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size));
  112. #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
  113. memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
  114. #endif
  115. return __ret;
  116. }
  117. else
  118. return 0;
  119. }
  120. void deallocate(pointer __p, size_type __n) {
  121. _STLP_ASSERT( (__p == 0) == (__n == 0) )
  122. if (__p != 0) {
  123. #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
  124. memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type));
  125. #endif
  126. _S_Alloc::deallocate(__p, __n * sizeof(value_type));
  127. }
  128. }
  129. size_type max_size() const _STLP_NOTHROW
  130. { return size_t(-1) / sizeof(_Tp); }
  131. void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
  132. void destroy(pointer _p) { _p->~_Tp(); }
  133. #if defined (_STLP_NO_EXTENSIONS)
  134. /* STLport extension giving rounded size of an allocated memory buffer
  135. * This method do not have to be part of a user defined allocator implementation
  136. * and won't even be called if such a function was granted.
  137. */
  138. protected:
  139. #endif
  140. _Tp* allocate(size_type __n, size_type& __allocated_n) {
  141. if (__n > max_size()) {
  142. _STLP_THROW_BAD_ALLOC;
  143. }
  144. if (__n != 0) {
  145. size_type __buf_size = __n * sizeof(value_type);
  146. _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size));
  147. #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
  148. memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
  149. #endif
  150. __allocated_n = __buf_size / sizeof(value_type);
  151. return __ret;
  152. }
  153. else
  154. return 0;
  155. }
  156. #if defined (_STLP_USE_PARTIAL_SPEC_WORKAROUND) && !defined (_STLP_FUNCTION_TMPL_PARTIAL_ORDER)
  157. void _M_swap_workaround(pthread_allocator<_Tp>& __x) {}
  158. #endif
  159. };
  160. _STLP_TEMPLATE_NULL
  161. class _STLP_CLASS_DECLSPEC pthread_allocator<void> {
  162. public:
  163. typedef size_t size_type;
  164. typedef ptrdiff_t difference_type;
  165. typedef void* pointer;
  166. typedef const void* const_pointer;
  167. typedef void value_type;
  168. #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
  169. template <class _NewType> struct rebind {
  170. typedef pthread_allocator<_NewType> other;
  171. };
  172. #endif
  173. };
  174. template <class _T1, class _T2>
  175. inline bool operator==(const pthread_allocator<_T1>&,
  176. const pthread_allocator<_T2>& a2)
  177. { return true; }
  178. #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER
  179. template <class _T1, class _T2>
  180. inline bool operator!=(const pthread_allocator<_T1>&,
  181. const pthread_allocator<_T2>&)
  182. { return false; }
  183. #endif
  184. #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
  185. template <class _Tp, class _Atype>
  186. struct _Alloc_traits<_Tp, pthread_allocator<_Atype> >
  187. { typedef pthread_allocator<_Tp> allocator_type; };
  188. #endif
  189. #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE)
  190. template <class _Tp1, class _Tp2>
  191. inline pthread_allocator<_Tp2>&
  192. __stl_alloc_rebind(pthread_allocator<_Tp1>& __x, const _Tp2*)
  193. { return (pthread_allocator<_Tp2>&)__x; }
  194. template <class _Tp1, class _Tp2>
  195. inline pthread_allocator<_Tp2>
  196. __stl_alloc_create(pthread_allocator<_Tp1>&, const _Tp2*)
  197. { return pthread_allocator<_Tp2>(); }
  198. #endif
  199. _STLP_MOVE_TO_PRIV_NAMESPACE
  200. template <class _Tp>
  201. struct __pthread_alloc_type_traits {
  202. typedef typename _IsSTLportClass<pthread_allocator<_Tp> >::_Ret _STLportAlloc;
  203. //The default allocator implementation which is recognize thanks to the
  204. //__stlport_class inheritance is a stateless object so:
  205. typedef _STLportAlloc has_trivial_default_constructor;
  206. typedef _STLportAlloc has_trivial_copy_constructor;
  207. typedef _STLportAlloc has_trivial_assignment_operator;
  208. typedef _STLportAlloc has_trivial_destructor;
  209. typedef _STLportAlloc is_POD_type;
  210. };
  211. _STLP_MOVE_TO_STD_NAMESPACE
  212. #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
  213. template <class _Tp>
  214. struct __type_traits<pthread_allocator<_Tp> > : _STLP_PRIV __pthread_alloc_type_traits<_Tp> {};
  215. #else
  216. _STLP_TEMPLATE_NULL
  217. struct __type_traits<pthread_allocator<char> > : _STLP_PRIV __pthread_alloc_type_traits<char> {};
  218. # if defined (_STLP_HAS_WCHAR_T)
  219. _STLP_TEMPLATE_NULL
  220. struct __type_traits<pthread_allocator<wchar_t> > : _STLP_PRIV __pthread_alloc_type_traits<wchar_t> {};
  221. # endif
  222. # if defined (_STLP_USE_PTR_SPECIALIZATIONS)
  223. _STLP_TEMPLATE_NULL
  224. struct __type_traits<pthread_allocator<void*> > : _STLP_PRIV __pthread_alloc_type_traits<void*> {};
  225. # endif
  226. #endif
  227. //
  228. // per_thread_allocator<> : this allocator always return memory to the same thread
  229. // it was allocated from.
  230. //
  231. template <class _Tp>
  232. class per_thread_allocator {
  233. typedef pthread_alloc _S_Alloc; // The underlying allocator.
  234. typedef pthread_alloc::__state_type __state_type;
  235. public:
  236. typedef size_t size_type;
  237. typedef ptrdiff_t difference_type;
  238. typedef _Tp* pointer;
  239. typedef const _Tp* const_pointer;
  240. typedef _Tp& reference;
  241. typedef const _Tp& const_reference;
  242. typedef _Tp value_type;
  243. #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
  244. template <class _NewType> struct rebind {
  245. typedef per_thread_allocator<_NewType> other;
  246. };
  247. #endif
  248. per_thread_allocator() _STLP_NOTHROW {
  249. _M_state = _S_Alloc::_S_get_per_thread_state();
  250. }
  251. per_thread_allocator(const per_thread_allocator<_Tp>& __a) _STLP_NOTHROW : _M_state(__a._M_state){}
  252. #if defined (_STLP_MEMBER_TEMPLATES) /* && defined (_STLP_FUNCTION_PARTIAL_ORDER) */
  253. template <class _OtherType> per_thread_allocator(const per_thread_allocator<_OtherType>& __a)
  254. _STLP_NOTHROW : _M_state(__a._M_state) {}
  255. #endif
  256. ~per_thread_allocator() _STLP_NOTHROW {}
  257. pointer address(reference __x) const { return &__x; }
  258. const_pointer address(const_reference __x) const { return &__x; }
  259. // __n is permitted to be 0. The C++ standard says nothing about what
  260. // the return value is when __n == 0.
  261. _Tp* allocate(size_type __n, const void* = 0) {
  262. if (__n > max_size()) {
  263. _STLP_THROW_BAD_ALLOC;
  264. }
  265. if (__n != 0) {
  266. size_type __buf_size = __n * sizeof(value_type);
  267. _Tp* __ret = __REINTERPRET_CAST(_Tp*, _S_Alloc::allocate(__buf_size, _M_state));
  268. #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
  269. memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
  270. #endif
  271. return __ret;
  272. }
  273. else
  274. return 0;
  275. }
  276. void deallocate(pointer __p, size_type __n) {
  277. _STLP_ASSERT( (__p == 0) == (__n == 0) )
  278. if (__p != 0) {
  279. #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
  280. memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type));
  281. #endif
  282. _S_Alloc::deallocate(__p, __n * sizeof(value_type), _M_state);
  283. }
  284. }
  285. size_type max_size() const _STLP_NOTHROW
  286. { return size_t(-1) / sizeof(_Tp); }
  287. void construct(pointer __p, const _Tp& __val) { new(__p) _Tp(__val); }
  288. void destroy(pointer _p) { _p->~_Tp(); }
  289. // state is being kept here
  290. __state_type* _M_state;
  291. #if defined (_STLP_NO_EXTENSIONS)
  292. /* STLport extension giving rounded size of an allocated memory buffer
  293. * This method do not have to be part of a user defined allocator implementation
  294. * and won't even be called if such a function was granted.
  295. */
  296. protected:
  297. #endif
  298. _Tp* allocate(size_type __n, size_type& __allocated_n) {
  299. if (__n > max_size()) {
  300. _STLP_THROW_BAD_ALLOC;
  301. }
  302. if (__n != 0) {
  303. size_type __buf_size = __n * sizeof(value_type);
  304. _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size, _M_state));
  305. #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
  306. memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
  307. #endif
  308. __allocated_n = __buf_size / sizeof(value_type);
  309. return __ret;
  310. }
  311. else
  312. return 0;
  313. }
  314. };
  315. _STLP_TEMPLATE_NULL
  316. class _STLP_CLASS_DECLSPEC per_thread_allocator<void> {
  317. public:
  318. typedef size_t size_type;
  319. typedef ptrdiff_t difference_type;
  320. typedef void* pointer;
  321. typedef const void* const_pointer;
  322. typedef void value_type;
  323. #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
  324. template <class _NewType> struct rebind {
  325. typedef per_thread_allocator<_NewType> other;
  326. };
  327. #endif
  328. };
  329. template <class _T1, class _T2>
  330. inline bool operator==(const per_thread_allocator<_T1>& __a1,
  331. const per_thread_allocator<_T2>& __a2)
  332. { return __a1._M_state == __a2._M_state; }
  333. #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER
  334. template <class _T1, class _T2>
  335. inline bool operator!=(const per_thread_allocator<_T1>& __a1,
  336. const per_thread_allocator<_T2>& __a2)
  337. { return __a1._M_state != __a2._M_state; }
  338. #endif
  339. #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
  340. template <class _Tp, class _Atype>
  341. struct _Alloc_traits<_Tp, per_thread_allocator<_Atype> >
  342. { typedef per_thread_allocator<_Tp> allocator_type; };
  343. #endif
  344. #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE)
  345. template <class _Tp1, class _Tp2>
  346. inline per_thread_allocator<_Tp2>&
  347. __stl_alloc_rebind(per_thread_allocator<_Tp1>& __x, const _Tp2*)
  348. { return (per_thread_allocator<_Tp2>&)__x; }
  349. template <class _Tp1, class _Tp2>
  350. inline per_thread_allocator<_Tp2>
  351. __stl_alloc_create(per_thread_allocator<_Tp1>&, const _Tp2*)
  352. { return per_thread_allocator<_Tp2>(); }
  353. #endif /* _STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE */
  354. _STLP_MOVE_TO_PRIV_NAMESPACE
  355. template <class _Tp>
  356. struct __perthread_alloc_type_traits {
  357. typedef typename _IsSTLportClass<per_thread_allocator<_Tp> >::_Ret _STLportAlloc;
  358. //The default allocator implementation which is recognize thanks to the
  359. //__stlport_class inheritance is a stateless object so:
  360. typedef __false_type has_trivial_default_constructor;
  361. typedef _STLportAlloc has_trivial_copy_constructor;
  362. typedef _STLportAlloc has_trivial_assignment_operator;
  363. typedef _STLportAlloc has_trivial_destructor;
  364. typedef __false_type is_POD_type;
  365. };
  366. _STLP_MOVE_TO_STD_NAMESPACE
  367. #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
  368. template <class _Tp>
  369. struct __type_traits<per_thread_allocator<_Tp> > : _STLP_PRIV __perthread_alloc_type_traits<_Tp> {};
  370. #else
  371. _STLP_TEMPLATE_NULL
  372. struct __type_traits<per_thread_allocator<char> > : _STLP_PRIV __perthread_alloc_type_traits<char> {};
  373. # if defined (_STLP_HAS_WCHAR_T)
  374. _STLP_TEMPLATE_NULL
  375. struct __type_traits<per_thread_allocator<wchar_t> > : _STLP_PRIV __perthread_alloc_type_traits<wchar_t> {};
  376. # endif
  377. # if defined (_STLP_USE_PTR_SPECIALIZATIONS)
  378. _STLP_TEMPLATE_NULL
  379. struct __type_traits<per_thread_allocator<void*> > : _STLP_PRIV __perthread_alloc_type_traits<void*> {};
  380. # endif
  381. #endif
  382. _STLP_END_NAMESPACE
  383. #endif /* _STLP_PTHREAD_ALLOC */
  384. // Local Variables:
  385. // mode:C++
  386. // End: