]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/stl/stl/_pthread_alloc.h
Add STLport 5.1.4
[polintos/scott/priv.git] / include / c++ / stl / stl / _pthread_alloc.h
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
26 #ifndef _STLP_PTHREAD_ALLOC_H
27 #define _STLP_PTHREAD_ALLOC_H
28
29 /*
30  * Pthread-specific node allocator.
31  * This is similar to the default allocator, except that free-list
32  * information is kept separately for each thread, avoiding locking.
33  * This should be reasonably fast even in the presence of threads.
34  * The down side is that storage may not be well-utilized.
35  * It is not an error to allocate memory in thread A and deallocate
36  * it in thread B.  But this effectively transfers ownership of the memory,
37  * so that it can only be reallocated by thread B.  Thus this can effectively
38  * result in a storage leak if it's done on a regular basis.
39  * It can also result in frequent sharing of
40  * cache lines among processors, with potentially serious performance
41  * consequences.
42  */
43
44 #if !defined (_STLP_PTHREADS)
45 #  error POSIX specific allocator implementation. Your system do not seems to \
46 have this interface so please comment the _STLP_USE_PERTHREAD_ALLOC macro \
47 or report to the STLport forum.
48 #endif
49
50 #if defined (_STLP_USE_NO_IOSTREAMS)
51 #  error You cannot use per thread allocator implementation without building \
52 STLport libraries.
53 #endif
54
55 #ifndef _STLP_INTERNAL_ALLOC_H
56 #  include <stl/_alloc.h>
57 #endif
58
59 _STLP_BEGIN_NAMESPACE
60
61 _STLP_MOVE_TO_PRIV_NAMESPACE
62
63 struct _Pthread_alloc_per_thread_state;
64
65 // Pthread-specific allocator.
66 class _STLP_CLASS_DECLSPEC _Pthread_alloc {
67 public: // but only for internal use:
68   typedef _Pthread_alloc_per_thread_state __state_type;
69   typedef char value_type;
70
71 public:
72   // Return a recycled or new per thread state.
73   static __state_type * _STLP_CALL _S_get_per_thread_state();
74
75   /* n must be > 0      */
76   static void * _STLP_CALL allocate(size_t& __n);
77
78   /* p may not be 0 */
79   static void _STLP_CALL deallocate(void *__p, size_t __n);
80
81   // boris : versions for per_thread_allocator
82   /* n must be > 0      */
83   static void * _STLP_CALL allocate(size_t& __n, __state_type* __a);
84
85   /* p may not be 0 */
86   static void _STLP_CALL deallocate(void *__p, size_t __n, __state_type* __a);
87
88   static void * _STLP_CALL reallocate(void *__p, size_t __old_sz, size_t& __new_sz);
89 };
90
91 _STLP_MOVE_TO_STD_NAMESPACE
92
93 typedef _STLP_PRIV _Pthread_alloc __pthread_alloc;
94 typedef __pthread_alloc pthread_alloc;
95
96 template <class _Tp>
97 class pthread_allocator : public __stlport_class<pthread_allocator<_Tp> > {
98   typedef pthread_alloc _S_Alloc;          // The underlying allocator.
99 public:
100   typedef size_t     size_type;
101   typedef ptrdiff_t  difference_type;
102   typedef _Tp*       pointer;
103   typedef const _Tp* const_pointer;
104   typedef _Tp&       reference;
105   typedef const _Tp& const_reference;
106   typedef _Tp        value_type;
107
108 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
109   template <class _NewType> struct rebind {
110     typedef pthread_allocator<_NewType> other;
111   };
112 #endif
113
114   pthread_allocator() _STLP_NOTHROW {}
115   pthread_allocator(const pthread_allocator<_Tp>& a) _STLP_NOTHROW {}
116
117 #if defined (_STLP_MEMBER_TEMPLATES) /* && defined (_STLP_FUNCTION_PARTIAL_ORDER) */
118   template <class _OtherType> pthread_allocator(const pthread_allocator<_OtherType>&)
119     _STLP_NOTHROW {}
120 #endif
121
122   ~pthread_allocator() _STLP_NOTHROW {}
123
124   pointer address(reference __x) const { return &__x; }
125   const_pointer address(const_reference __x) const { return &__x; }
126
127   // __n is permitted to be 0.  The C++ standard says nothing about what
128   // the return value is when __n == 0.
129   _Tp* allocate(size_type __n, const void* = 0) {
130     if (__n > max_size()) {
131       __THROW_BAD_ALLOC;
132     }
133     if (__n != 0) {
134       size_type __buf_size = __n * sizeof(value_type);
135       _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size));
136 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
137       if (__ret != 0) {
138         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
139       }
140 #endif
141       return __ret;
142     }
143     else
144       return 0;
145   }
146
147   void deallocate(pointer __p, size_type __n) {
148     _STLP_ASSERT( (__p == 0) == (__n == 0) )
149     if (__p != 0) {
150 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
151       memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type));
152 #endif
153       _S_Alloc::deallocate(__p, __n * sizeof(value_type));
154     }
155   }
156
157   size_type max_size() const _STLP_NOTHROW
158   { return size_t(-1) / sizeof(_Tp); }
159
160   void construct(pointer __p, const _Tp& __val) { _STLP_PLACEMENT_NEW (__p) _Tp(__val); }
161   void destroy(pointer _p) { _p->~_Tp(); }
162
163 #if defined (_STLP_NO_EXTENSIONS)
164   /* STLport extension giving rounded size of an allocated memory buffer
165    * This method do not have to be part of a user defined allocator implementation
166    * and won't even be called if such a function was granted.
167    */
168 protected:
169 #endif
170   _Tp* allocate(size_type __n, size_type& __allocated_n) {
171     if (__n > max_size()) {
172       __THROW_BAD_ALLOC;
173     }
174     if (__n != 0) {
175       size_type __buf_size = __n * sizeof(value_type);
176       _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size));
177 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
178       if (__ret != 0) {
179         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
180       }
181 #endif
182       __allocated_n = __buf_size / sizeof(value_type);
183       return __ret;
184     }
185     else
186       return 0;
187   }
188 };
189
190 _STLP_TEMPLATE_NULL
191 class _STLP_CLASS_DECLSPEC pthread_allocator<void> {
192 public:
193   typedef size_t      size_type;
194   typedef ptrdiff_t   difference_type;
195   typedef void*       pointer;
196   typedef const void* const_pointer;
197   typedef void        value_type;
198 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
199   template <class _NewType> struct rebind {
200     typedef pthread_allocator<_NewType> other;
201   };
202 #endif
203 };
204
205 template <class _T1, class _T2>
206 inline bool operator==(const pthread_allocator<_T1>&,
207                        const pthread_allocator<_T2>& a2)
208 { return true; }
209
210 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER
211 template <class _T1, class _T2>
212 inline bool operator!=(const pthread_allocator<_T1>&,
213                        const pthread_allocator<_T2>&)
214 { return false; }
215 #endif
216
217
218 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
219
220 #  if defined (_STLP_USE_RAW_SGI_ALLOCATORS)
221 template <class _Tp>
222 struct _Alloc_traits<_Tp, _Pthread_alloc>
223 { typedef __allocator<_Tp, _Pthread_alloc> allocator_type; };
224 #  endif
225
226 template <class _Tp, class _Atype>
227 struct _Alloc_traits<_Tp, pthread_allocator<_Atype> >
228 { typedef pthread_allocator<_Tp> allocator_type; };
229
230 #endif
231
232 #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE)
233
234 template <class _Tp1, class _Tp2>
235 inline pthread_allocator<_Tp2>&
236 __stl_alloc_rebind(pthread_allocator<_Tp1>& __x, const _Tp2*)
237 { return (pthread_allocator<_Tp2>&)__x; }
238
239 template <class _Tp1, class _Tp2>
240 inline pthread_allocator<_Tp2>
241 __stl_alloc_create(pthread_allocator<_Tp1>&, const _Tp2*)
242 { return pthread_allocator<_Tp2>(); }
243
244 #endif
245
246 _STLP_MOVE_TO_PRIV_NAMESPACE
247
248 template <class _Tp>
249 struct __pthread_alloc_type_traits {
250   typedef typename _IsSTLportClass<pthread_allocator<_Tp> >::_Ret _STLportAlloc;
251   //The default allocator implementation which is recognize thanks to the
252   //__stlport_class inheritance is a stateless object so:
253   typedef _STLportAlloc has_trivial_default_constructor;
254   typedef _STLportAlloc has_trivial_copy_constructor;
255   typedef _STLportAlloc has_trivial_assignment_operator;
256   typedef _STLportAlloc has_trivial_destructor;
257   typedef _STLportAlloc is_POD_type;
258 };
259
260 _STLP_MOVE_TO_STD_NAMESPACE
261
262 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
263 template <class _Tp>
264 struct __type_traits<pthread_allocator<_Tp> > : _STLP_PRIV __pthread_alloc_type_traits<_Tp> {};
265 #else
266 _STLP_TEMPLATE_NULL
267 struct __type_traits<pthread_allocator<char> > : _STLP_PRIV __pthread_alloc_type_traits<char> {};
268 #  if defined (_STLP_HAS_WCHAR_T)
269 _STLP_TEMPLATE_NULL
270 struct __type_traits<pthread_allocator<wchar_t> > : _STLP_PRIV __pthread_alloc_type_traits<wchar_t> {};
271 #  endif
272 #  if defined (_STLP_USE_PTR_SPECIALIZATIONS)
273 _STLP_TEMPLATE_NULL
274 struct __type_traits<pthread_allocator<void*> > : _STLP_PRIV __pthread_alloc_type_traits<void*> {};
275 #  endif
276 #endif
277
278 //
279 // per_thread_allocator<> : this allocator always return memory to the same thread
280 // it was allocated from.
281 //
282
283 template <class _Tp>
284 class per_thread_allocator {
285   typedef pthread_alloc _S_Alloc;          // The underlying allocator.
286   typedef pthread_alloc::__state_type __state_type;
287 public:
288   typedef size_t     size_type;
289   typedef ptrdiff_t  difference_type;
290   typedef _Tp*       pointer;
291   typedef const _Tp* const_pointer;
292   typedef _Tp&       reference;
293   typedef const _Tp& const_reference;
294   typedef _Tp        value_type;
295
296 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
297   template <class _NewType> struct rebind {
298     typedef per_thread_allocator<_NewType> other;
299   };
300 #endif
301
302   per_thread_allocator() _STLP_NOTHROW {
303     _M_state = _S_Alloc::_S_get_per_thread_state();
304   }
305   per_thread_allocator(const per_thread_allocator<_Tp>& __a) _STLP_NOTHROW : _M_state(__a._M_state){}
306
307 #if defined (_STLP_MEMBER_TEMPLATES) /* && defined (_STLP_FUNCTION_PARTIAL_ORDER) */
308   template <class _OtherType> per_thread_allocator(const per_thread_allocator<_OtherType>& __a)
309     _STLP_NOTHROW : _M_state(__a._M_state) {}
310 #endif
311
312   ~per_thread_allocator() _STLP_NOTHROW {}
313
314   pointer address(reference __x) const { return &__x; }
315   const_pointer address(const_reference __x) const { return &__x; }
316
317   // __n is permitted to be 0.  The C++ standard says nothing about what
318   // the return value is when __n == 0.
319   _Tp* allocate(size_type __n, const void* = 0) {
320     if (__n > max_size()) {
321       __THROW_BAD_ALLOC;
322     }
323     if (__n != 0) {
324       size_type __buf_size = __n * sizeof(value_type);
325       _Tp* __ret = __REINTERPRET_CAST(_Tp*, _S_Alloc::allocate(__buf_size, _M_state));
326 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
327       if (__ret != 0) {
328         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
329       }
330 #endif
331       return __ret;
332     }
333     else
334       return 0;
335   }
336
337   void deallocate(pointer __p, size_type __n) {
338     _STLP_ASSERT( (__p == 0) == (__n == 0) )
339     if (__p != 0) {
340 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
341       memset((char*)__p, _STLP_SHRED_BYTE, __n * sizeof(value_type));
342 #endif
343       _S_Alloc::deallocate(__p, __n * sizeof(value_type), _M_state);
344     }
345   }
346
347   size_type max_size() const _STLP_NOTHROW
348   { return size_t(-1) / sizeof(_Tp); }
349
350   void construct(pointer __p, const _Tp& __val) { _STLP_PLACEMENT_NEW (__p) _Tp(__val); }
351   void destroy(pointer _p) { _p->~_Tp(); }
352
353   // state is being kept here
354   __state_type* _M_state;
355
356 #if defined (_STLP_NO_EXTENSIONS)
357   /* STLport extension giving rounded size of an allocated memory buffer
358    * This method do not have to be part of a user defined allocator implementation
359    * and won't even be called if such a function was granted.
360    */
361 protected:
362 #endif
363   _Tp* allocate(size_type __n, size_type& __allocated_n) {
364     if (__n > max_size()) {
365       __THROW_BAD_ALLOC;
366     }
367     if (__n != 0) {
368       size_type __buf_size = __n * sizeof(value_type);
369       _Tp* __ret = __REINTERPRET_CAST(value_type*, _S_Alloc::allocate(__buf_size, _M_state));
370 #if defined (_STLP_DEBUG_UNINITIALIZED) && !defined (_STLP_DEBUG_ALLOC)
371       if (__ret != 0) {
372         memset((char*)__ret, _STLP_SHRED_BYTE, __buf_size);
373       }
374 #endif
375       __allocated_n = __buf_size / sizeof(value_type);
376       return __ret;
377     }
378     else
379       return 0;
380   }
381 };
382
383 _STLP_TEMPLATE_NULL
384 class _STLP_CLASS_DECLSPEC per_thread_allocator<void> {
385 public:
386   typedef size_t      size_type;
387   typedef ptrdiff_t   difference_type;
388   typedef void*       pointer;
389   typedef const void* const_pointer;
390   typedef void        value_type;
391 #ifdef _STLP_MEMBER_TEMPLATE_CLASSES
392   template <class _NewType> struct rebind {
393     typedef per_thread_allocator<_NewType> other;
394   };
395 #endif
396 };
397
398 template <class _T1, class _T2>
399 inline bool operator==(const per_thread_allocator<_T1>& __a1,
400                        const per_thread_allocator<_T2>& __a2)
401 { return __a1._M_state == __a2._M_state; }
402
403 #ifdef _STLP_FUNCTION_TMPL_PARTIAL_ORDER
404 template <class _T1, class _T2>
405 inline bool operator!=(const per_thread_allocator<_T1>& __a1,
406                        const per_thread_allocator<_T2>& __a2)
407 { return __a1._M_state != __a2._M_state; }
408 #endif
409
410
411 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
412
413 template <class _Tp, class _Atype>
414 struct _Alloc_traits<_Tp, per_thread_allocator<_Atype> >
415 { typedef per_thread_allocator<_Tp> allocator_type; };
416
417 #endif
418
419 #if defined (_STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE)
420
421 template <class _Tp1, class _Tp2>
422 inline per_thread_allocator<_Tp2>&
423 __stl_alloc_rebind(per_thread_allocator<_Tp1>& __x, const _Tp2*)
424 { return (per_thread_allocator<_Tp2>&)__x; }
425
426 template <class _Tp1, class _Tp2>
427 inline per_thread_allocator<_Tp2>
428 __stl_alloc_create(per_thread_allocator<_Tp1>&, const _Tp2*)
429 { return per_thread_allocator<_Tp2>(); }
430
431 #endif /* _STLP_DONT_SUPPORT_REBIND_MEMBER_TEMPLATE */
432
433 _STLP_MOVE_TO_PRIV_NAMESPACE
434
435 template <class _Tp>
436 struct __perthread_alloc_type_traits {
437   typedef typename _IsSTLportClass<per_thread_allocator<_Tp> >::_Ret _STLportAlloc;
438   //The default allocator implementation which is recognize thanks to the
439   //__stlport_class inheritance is a stateless object so:
440   typedef __false_type has_trivial_default_constructor;
441   typedef _STLportAlloc has_trivial_copy_constructor;
442   typedef _STLportAlloc has_trivial_assignment_operator;
443   typedef _STLportAlloc has_trivial_destructor;
444   typedef __false_type is_POD_type;
445 };
446
447 _STLP_MOVE_TO_STD_NAMESPACE
448
449 #if defined (_STLP_CLASS_PARTIAL_SPECIALIZATION)
450 template <class _Tp>
451 struct __type_traits<per_thread_allocator<_Tp> > : _STLP_PRIV __perthread_alloc_type_traits<_Tp> {};
452 #else
453 _STLP_TEMPLATE_NULL
454 struct __type_traits<per_thread_allocator<char> > : _STLP_PRIV __perthread_alloc_type_traits<char> {};
455 #  if defined (_STLP_HAS_WCHAR_T)
456 _STLP_TEMPLATE_NULL
457 struct __type_traits<per_thread_allocator<wchar_t> > : _STLP_PRIV __perthread_alloc_type_traits<wchar_t> {};
458 #  endif
459 #  if defined (_STLP_USE_PTR_SPECIALIZATIONS)
460 _STLP_TEMPLATE_NULL
461 struct __type_traits<per_thread_allocator<void*> > : _STLP_PRIV __perthread_alloc_type_traits<void*> {};
462 #  endif
463 #endif
464
465
466 _STLP_END_NAMESPACE
467
468 #endif /* _STLP_PTHREAD_ALLOC */
469
470 // Local Variables:
471 // mode:C++
472 // End: