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