1 /*
2 *
3 * Copyright (c) 1997
4 * Moscow Center for SPARC Technology
5 *
6 * Copyright (c) 1999
7 * Boris Fomitchev
8 *
9 * This material is provided "as is", with absolutely no warranty expressed
10 * or implied. Any use is at your own risk.
11 *
12 * Permission to use or copy this software for any purpose is hereby granted
13 * without fee, provided the above notices are retained on all copies.
14 * Permission to modify the code and to distribute modified code is granted,
15 * provided the above notices are retained, and a notice that the code was
16 * modified is included with the above copyright notice.
17 *
18 */
19
20 #ifndef _STLP_DEBUG_C
21 #define _STLP_DEBUG_C
22
23 #if defined (_STLP_DEBUG)
24 #if defined (_STLP_THREADS)
25 # if !defined (_STLP_NEED_MUTABLE)
26 # define _STLP_ACQUIRE_LOCK(_Lock) _Lock._M_acquire_lock();
27 # define _STLP_RELEASE_LOCK(_Lock) _Lock._M_release_lock();
28 # else
29 # define _STLP_ACQUIRE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_acquire_lock();
30 # define _STLP_RELEASE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_release_lock();
31 # endif /* _STLP_NEED_MUTABLE */
32 #else
33 # define _STLP_ACQUIRE_LOCK(_Lock)
34 # define _STLP_RELEASE_LOCK(_Lock)
35 #endif /* _STLP_THREADS */
36
37 _STLP_BEGIN_NAMESPACE
38 _STLP_MOVE_TO_PRIV_NAMESPACE
39
40 //==========================================================
41 // global non-inline functions
42 //==========================================================
43 // [ i1, i2)
44 #if !defined (__DMC__)
45 template <class _Iterator>
46 inline bool _STLP_CALL
__in_range_aux(const _Iterator & __it,const _Iterator & __first,const _Iterator & __last,const random_access_iterator_tag &)47 __in_range_aux(const _Iterator& __it, const _Iterator& __first,
48 const _Iterator& __last, const random_access_iterator_tag &) {
49 return ( __it >= __first &&
50 __it < __last);
51 }
52 #endif
53
54 template <class _Iterator1, class _Iterator>
55 #if defined (_STLP_MSVC) && (_STLP_MSVC >= 1100)
__in_range_aux(_Iterator1 __it,const _Iterator & __first,const _Iterator & __last,const forward_iterator_tag &)56 inline bool _STLP_CALL __in_range_aux(_Iterator1 __it, const _Iterator& __first,
57 #else
58 inline bool _STLP_CALL __in_range_aux(const _Iterator1& __it, const _Iterator& __first,
59 #endif
60 const _Iterator& __last, const forward_iterator_tag &) {
61 _Iterator1 __i(__first);
62 for (; __i != __last && __i != __it; ++__i);
63 return (__i != __last);
64 }
65
66 #if defined (_STLP_NONTEMPL_BASE_MATCH_BUG)
67 template <class _Iterator1, class _Iterator>
68 inline bool _STLP_CALL
__in_range_aux(const _Iterator1 & __it,const _Iterator & __first,const _Iterator & __last,const bidirectional_iterator_tag &)69 __in_range_aux(const _Iterator1& __it, const _Iterator& __first,
70 const _Iterator& __last, const bidirectional_iterator_tag &) {
71 _Iterator1 __i(__first);
72 for (; __i != __last && __i != __it; ++__i);
73 return (__i != __last);
74 }
75 #endif
76
77 template <class _Iterator>
__check_range_aux(const _Iterator & __first,const _Iterator & __last,const __false_type &)78 bool _STLP_CALL __check_range_aux(const _Iterator& __first, const _Iterator& __last,
79 const __false_type& /*_IsIntegral*/) {
80 _STLP_VERBOSE_RETURN(__valid_range(__first,__last), _StlMsg_INVALID_RANGE )
81 return true;
82 }
83
84 template <class _Integral>
__check_range_aux(_Integral,_Integral,const __true_type &)85 bool _STLP_CALL __check_range_aux(_Integral /*__first*/, _Integral /*__last*/,
86 const __true_type& /*_IsIntegral*/)
87 { return true; }
88
89 template <class _Iterator>
__check_range(const _Iterator & __first,const _Iterator & __last)90 bool _STLP_CALL __check_range(const _Iterator& __first, const _Iterator& __last) {
91 typedef typename _IsIntegral<_Iterator>::_Ret _Integral;
92 return __check_range_aux(__first, __last, _Integral());
93 }
94
95 template <class _Iterator>
__check_range(const _Iterator & __it,const _Iterator & __start,const _Iterator & __finish)96 bool _STLP_CALL __check_range(const _Iterator& __it,
97 const _Iterator& __start, const _Iterator& __finish) {
98 _STLP_VERBOSE_RETURN(__in_range(__it, __start, __finish),
99 _StlMsg_NOT_IN_RANGE_1)
100 return true;
101 }
102
103 template <class _Iterator>
__check_range(const _Iterator & __first,const _Iterator & __last,const _Iterator & __start,const _Iterator & __finish)104 bool _STLP_CALL __check_range(const _Iterator& __first, const _Iterator& __last,
105 const _Iterator& __start, const _Iterator& __finish) {
106 _STLP_VERBOSE_RETURN(__in_range(__first, __last, __start, __finish),
107 _StlMsg_NOT_IN_RANGE_2)
108 return true;
109 }
110
111 template <class _Tp>
__check_ptr_range(const _Tp * __first,const _Tp * __last)112 bool _STLP_CALL __check_ptr_range(const _Tp* __first, const _Tp* __last) {
113 _STLP_VERBOSE_RETURN((__first != 0 || __last == 0), _StlMsg_INVALID_ARGUMENT)
114 _STLP_VERBOSE_RETURN(__valid_range(__first, __last, random_access_iterator_tag()),
115 _StlMsg_INVALID_RANGE)
116 return true;
117 }
118
119 //===============================================================
120 template <class _Iterator>
__invalidate_range(const __owned_list * __base,const _Iterator & __first,const _Iterator & __last)121 void _STLP_CALL __invalidate_range(const __owned_list* __base,
122 const _Iterator& __first,
123 const _Iterator& __last) {
124 typedef __owned_link _L_type;
125 _STLP_ACQUIRE_LOCK(__base->_M_lock)
126 _L_type* __prev = __CONST_CAST(_L_type*, &__base->_M_node);
127 _L_type* __pos = __prev->_M_next;
128
129 while (__pos != 0) {
130 if (!(&__first == __STATIC_CAST(_Iterator*, __pos) || &__last == __STATIC_CAST(_Iterator*, __pos)) &&
131 __in_range_aux(__STATIC_CAST(_Iterator*, __pos)->_M_iterator,
132 __first._M_iterator, __last._M_iterator,
133 _STLP_ITERATOR_CATEGORY(__first, _Iterator))) {
134 __pos->_M_owner = 0;
135 __prev->_M_next = __pos->_M_next;
136 }
137 else {
138 __prev = __pos;
139 }
140 __pos = __prev->_M_next;
141 }
142 _STLP_RELEASE_LOCK(__base->_M_lock)
143 }
144
145 template <class _Iterator>
__invalidate_iterator(const __owned_list * __base,const _Iterator & __it)146 void _STLP_CALL __invalidate_iterator(const __owned_list* __base,
147 const _Iterator& __it) {
148 typedef __owned_link _L_type;
149 _STLP_ACQUIRE_LOCK(__base->_M_lock)
150 _L_type* __prev = __CONST_CAST(_L_type*, &__base->_M_node);
151 _L_type* __pos = __prev->_M_next;
152 while (__pos != 0) {
153 // this requires safe iterators to be derived from __owned_link
154 if ((__pos != __STATIC_CAST(const _L_type*, &__it)) &&
155 (__STATIC_CAST(_Iterator*, __pos)->_M_iterator == __it._M_iterator)) {
156 __pos->_M_owner = 0;
157 __prev->_M_next = __pos->_M_next;
158 }
159 else {
160 __prev = __pos;
161 }
162 __pos = __prev->_M_next;
163 }
164 _STLP_RELEASE_LOCK(__base->_M_lock)
165 }
166
167 template <class _Iterator>
__change_range_owner(const _Iterator & __first,const _Iterator & __last,const __owned_list * __dst)168 void _STLP_CALL __change_range_owner(const _Iterator& __first,
169 const _Iterator& __last,
170 const __owned_list* __dst) {
171 if (__first._Owner() == __dst)
172 return;
173
174 typedef __owned_link _L_type;
175 // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
176 //_STLP_ACQUIRE_LOCK(__base->_M_lock)
177 __owned_list *__base = __CONST_CAST(__owned_list*, __first._Owner());
178 _L_type* __src_prev = &__base->_M_node;
179 _L_type* __pos = __src_prev->_M_next;
180 _L_type* __dst_prev = __CONST_CAST(_L_type*, &__dst->_M_node);
181
182 while (__pos != 0) {
183 if (!(&__first == __STATIC_CAST(_Iterator*, __pos) || &__last == __STATIC_CAST(_Iterator*, __pos)) &&
184 __in_range_aux(__STATIC_CAST(_Iterator*, __pos)->_M_iterator,
185 __first._M_iterator, __last._M_iterator,
186 _STLP_ITERATOR_CATEGORY(__first, _Iterator))) {
187 __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
188 //remove __pos from __base:
189 __src_prev->_M_next = __pos->_M_next;
190 //add __pos to __dst:
191 __pos->_M_next = __dst_prev->_M_next;
192 __dst_prev->_M_next = __pos;
193 }
194 else {
195 __src_prev = __pos;
196 }
197 __pos = __src_prev->_M_next;
198 }
199 //_STLP_RELEASE_LOCK(__base->_M_lock)
200 }
201
202 template <class _Iterator>
__change_ite_owner(const _Iterator & __it,const __owned_list * __dst)203 void _STLP_CALL __change_ite_owner(const _Iterator& __it,
204 const __owned_list* __dst) {
205 if (__it._Owner() == __dst)
206 return;
207
208 typedef __owned_link _L_type;
209 // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
210 //_STLP_ACQUIRE_LOCK(__base->_M_lock)
211 __owned_list *__base = __CONST_CAST(__owned_list*, __it._Owner());
212 _L_type* __prev = &__base->_M_node;
213 _L_type* __pos = __prev->_M_next;
214 _L_type* __dst_prev = __CONST_CAST(_L_type*, &__dst->_M_node);
215
216 while (__pos != 0) {
217 // this requires safe iterators to be derived from __owned_link
218 if ((__pos != __STATIC_CAST(const _L_type*, &__it)) &&
219 (__STATIC_CAST(_Iterator*, __pos)->_M_iterator == __it._M_iterator)) {
220 __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
221 //remove __pos from __base:
222 __prev->_M_next = __pos->_M_next;
223 //add __pos to __dst:
224 __pos->_M_next = __dst_prev->_M_next;
225 __dst_prev->_M_next = __pos;
226 }
227 else {
228 __prev = __pos;
229 }
230 __pos = __prev->_M_next;
231 }
232 //_STLP_RELEASE_LOCK(__base->_M_lock)
233 }
234
235 _STLP_MOVE_TO_STD_NAMESPACE
236 _STLP_END_NAMESPACE
237
238 #endif /* _STLP_DEBUG */
239
240 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
241
242 # ifndef _STLP_INTERNAL_CSTDLIB
243 # include <stl/_cstdlib.h>
244 # endif
245
246 //==========================================================
247 // .c section
248 // owned_list non-inline methods and global functions
249 //==========================================================
250
251 # if defined (_STLP_ASSERTIONS)
252
253 _STLP_BEGIN_NAMESPACE
254 _STLP_MOVE_TO_PRIV_NAMESPACE
255
256 # if !defined (_STLP_STRING_LITERAL)
257 # define _STLP_STRING_LITERAL(__x) __x
258 # endif
259
260 # if defined (_STLP_USE_WIDE_INTERFACE)
261 // note: WinCE needs this to format single-byte strings in __stl_debug_engine::_Message
262 # define _STLP_PERCENT_S "%hs"
263 # else
264 # define _STLP_PERCENT_S "%s"
265 # endif /* _STLP_USE_WIDE_INTERFACE */
266
267 # define _STLP_MESSAGE_TABLE_BODY = { \
268 _STLP_STRING_LITERAL("\n" _STLP_PERCENT_S "(%d): STL error: " _STLP_PERCENT_S "\n"), \
269 _STLP_STRING_LITERAL(_STLP_PERCENT_S "(%d): STL assertion failure : " _STLP_PERCENT_S "\n" _STLP_ASSERT_MSG_TRAILER), \
270 _STLP_STRING_LITERAL("\n" _STLP_PERCENT_S "(%d): STL error : " _STLP_PERCENT_S "\n" _STLP_PERCENT_S "(%d): STL assertion failure: " _STLP_PERCENT_S " \n" _STLP_ASSERT_MSG_TRAILER), \
271 _STLP_STRING_LITERAL("Invalid argument to operation (see operation documentation)"), \
272 _STLP_STRING_LITERAL("Taking an iterator out of destroyed (or otherwise corrupted) container"), \
273 _STLP_STRING_LITERAL("Trying to extract an object out from empty container"),\
274 _STLP_STRING_LITERAL("Past-the-end iterator could not be erased"), \
275 _STLP_STRING_LITERAL("Index out of bounds"), \
276 _STLP_STRING_LITERAL("Container doesn't own the iterator"), \
277 _STLP_STRING_LITERAL("Container is owner of the iterator, but should not"), \
278 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) iterator used"), \
279 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) lefthand iterator in expression"), \
280 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) righthand iterator in expression"), \
281 _STLP_STRING_LITERAL("Iterators used in expression are from different owners"), \
282 _STLP_STRING_LITERAL("Iterator could not be dereferenced (past-the-end ?)"), \
283 _STLP_STRING_LITERAL("Range [first,last) is invalid"), \
284 _STLP_STRING_LITERAL("Iterator is not in range [first,last)"), \
285 _STLP_STRING_LITERAL("Range [first,last) is not in range [start,finish)"), \
286 _STLP_STRING_LITERAL("The advance would produce invalid iterator"), \
287 _STLP_STRING_LITERAL("Iterator is singular (advanced beyond the bounds ?)"), \
288 _STLP_STRING_LITERAL("Invalid strict weak ordering predicate, if pred(a, b) then we should have !pred(b, a)"), \
289 _STLP_STRING_LITERAL("Invalid equivalent predicate, if pred(a, b) then we should have pred(b, a)"), \
290 _STLP_STRING_LITERAL("Memory block deallocated twice"), \
291 _STLP_STRING_LITERAL("Deallocating a block that was never allocated"), \
292 _STLP_STRING_LITERAL("Deallocating a memory block allocated for another type"), \
293 _STLP_STRING_LITERAL("Size of block passed to deallocate() doesn't match block size"), \
294 _STLP_STRING_LITERAL("Pointer underrun - safety margin at front of memory block overwritten"), \
295 _STLP_STRING_LITERAL("Pointer overrrun - safety margin at back of memory block overwritten"), \
296 _STLP_STRING_LITERAL("Attempt to dereference null pointer returned by auto_ptr::get()"), \
297 _STLP_STRING_LITERAL("Memory allocation function returned a wrongly align memory block"), \
298 _STLP_STRING_LITERAL("Unknown problem") \
299 }
300
301 # if (_STLP_STATIC_TEMPLATE_DATA > 0)
302 template <class _Dummy>
303 const char* __stl_debug_engine<_Dummy>::_Message_table[_StlMsg_MAX] _STLP_MESSAGE_TABLE_BODY;
304
305 # if (defined (__CYGWIN__) || defined (__MINGW32__)) && \
306 defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT)
307 /*
308 * Under cygwin, when STLport is used as a shared library, the id needs
309 * to be specified as imported otherwise they will be duplicated in the
310 * calling executable.
311 */
312 _STLP_TEMPLATE_NULL
313 _STLP_DECLSPEC const char* __stl_debug_engine<bool>::_Message_table[_StlMsg_MAX];
314 # endif
315
316 # else
317 __DECLARE_INSTANCE(const char*, __stl_debug_engine<bool>::_Message_table[_StlMsg_MAX],
318 _STLP_MESSAGE_TABLE_BODY);
319 # endif
320
321 # undef _STLP_STRING_LITERAL
322 # undef _STLP_PERCENT_S
323
324 _STLP_MOVE_TO_STD_NAMESPACE
325 _STLP_END_NAMESPACE
326
327 // abort()
328 # ifndef _STLP_INTERNAL_CSTDLIB
329 # include <stl/_cstdlib.h>
330 # endif
331
332 # if !defined (_STLP_DEBUG_MESSAGE)
333 # ifndef _STLP_INTERNAL_CSTDARG
334 # include <stl/_cstdarg.h>
335 # endif
336 # ifndef _STLP_INTERNAL_CSTDIO
337 # include <stl/_cstdio.h>
338 # endif
339 # if defined (_STLP_DEBUG_MODE_THROWS) && !defined (_STLP_RANGE_ERRORS_H)
340 # include <stl/_range_errors.h>
341 # endif
342
343 _STLP_BEGIN_NAMESPACE
344 _STLP_MOVE_TO_PRIV_NAMESPACE
345
346 template <class _Dummy>
347 void _STLP_CALL
_Message(const char * __format_str,...)348 __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...) {
349 STLPORT_CSTD::va_list __args;
350 va_start( __args, __format_str );
351
352 # if !defined (_STLP_DEBUG_MODE_THROWS)
353 # if defined (_STLP_USE_WIDE_INTERFACE)
354 TCHAR __buffer[512];
355 int _convert = strlen(__format_str) + 1;
356 LPWSTR _lpw = (LPWSTR)alloca(_convert * sizeof(wchar_t));
357 _lpw[0] = '\0';
358 MultiByteToWideChar(GetACP(), 0, __format_str, -1, _lpw, _convert);
359 wvsprintf(__buffer, _lpw, __args);
360 _STLP_WINCE_TRACE(__buffer);
361 # elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
362 char __buffer [4096];
363
364 # if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
365 vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
366 # else
367 vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
368 # endif
369
370 OutputDebugStringA(__buffer);
371
372 # elif defined (__amigaos__)
373 STLPORT_CSTD::vfprintf(stderr, __format_str, (char *)__args);
374 # else
375 STLPORT_CSTD::vfprintf(stderr, __format_str, __args);
376 # endif
377 # else
378 char __buffer[4096];
379
380 # if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
381 vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
382 # elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
383 vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
384 # else
385 vsprintf(__buffer, __format_str, __args);
386 # endif
387 # endif
388
389 # ifdef _STLP_DEBUG_MESSAGE_POST
390 _STLP_DEBUG_MESSAGE_POST
391 # endif
392
393 va_end(__args);
394
395 # if defined (_STLP_DEBUG_MODE_THROWS)
396 __stl_throw_runtime_error(__buffer);
397 # endif
398 }
399
400 _STLP_MOVE_TO_STD_NAMESPACE
401 _STLP_END_NAMESPACE
402
403 # else
404 _STLP_BEGIN_NAMESPACE
405 _STLP_MOVE_TO_PRIV_NAMESPACE
406 template <class _Dummy>
407 void _STLP_CALL
408 __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...)
409 {}
410 _STLP_MOVE_TO_STD_NAMESPACE
411 _STLP_END_NAMESPACE
412 # endif /* _STLP_DEBUG_MESSAGE */
413
414 _STLP_BEGIN_NAMESPACE
415 _STLP_MOVE_TO_PRIV_NAMESPACE
416
417 template <class _Dummy>
418 void _STLP_CALL
_IndexedError(int __error_ind,const char * __f,int __l)419 __stl_debug_engine<_Dummy>::_IndexedError(int __error_ind, const char* __f, int __l) {
420 __stl_debug_message(_Message_table[_StlFormat_ERROR_RETURN],
421 __f, __l, _Message_table[__error_ind]);
422 }
423
424 template <class _Dummy>
425 void _STLP_CALL
_VerboseAssert(const char * __expr,int __error_ind,const char * __f,int __l)426 __stl_debug_engine<_Dummy>::_VerboseAssert(const char* __expr, int __error_ind, const char* __f, int __l) {
427 __stl_debug_message(_Message_table[_StlFormat_VERBOSE_ASSERTION_FAILURE],
428 __f, __l, _Message_table[__error_ind], __f, __l, __expr);
429 __stl_debug_terminate();
430 }
431
432 template <class _Dummy>
433 void _STLP_CALL
_Assert(const char * __expr,const char * __f,int __l)434 __stl_debug_engine<_Dummy>::_Assert(const char* __expr, const char* __f, int __l) {
435 __stl_debug_message(_Message_table[_StlFormat_ASSERTION_FAILURE],__f, __l, __expr);
436 __stl_debug_terminate();
437 }
438
439 // if exceptions are present, sends unique exception
440 // if not, calls abort() to terminate
441 template <class _Dummy>
442 void _STLP_CALL
_Terminate()443 __stl_debug_engine<_Dummy>::_Terminate()
444 { _STLP_ABORT(); }
445
446 _STLP_MOVE_TO_STD_NAMESPACE
447 _STLP_END_NAMESPACE
448
449 # endif /* _STLP_ASSERTIONS */
450
451 # if defined (_STLP_DEBUG)
452
453 _STLP_BEGIN_NAMESPACE
454 _STLP_MOVE_TO_PRIV_NAMESPACE
455
456 //==========================================================
457 // owned_list non-inline methods
458 //==========================================================
459
460 template <class _Dummy>
461 void _STLP_CALL
_Invalidate_all(__owned_list * __l)462 __stl_debug_engine<_Dummy>::_Invalidate_all(__owned_list* __l) {
463 _STLP_ACQUIRE_LOCK(__l->_M_lock);
464 _Stamp_all(__l, 0);
465 __l->_M_node._M_next =0;
466 _STLP_RELEASE_LOCK(__l->_M_lock);
467 }
468
469 // boris : this is unasafe routine; should be used from within critical section only !
470 template <class _Dummy>
471 void _STLP_CALL
_Stamp_all(__owned_list * __l,__owned_list * __o)472 __stl_debug_engine<_Dummy>::_Stamp_all(__owned_list* __l, __owned_list* __o) {
473 // crucial
474 if (__l->_M_node._M_owner) {
475 for (__owned_link* __pos = (__owned_link*)__l->_M_node._M_next;
476 __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
477 _STLP_ASSERT(__pos->_Owner()== __l)
478 __pos->_M_owner=__o;
479 }
480 }
481 }
482
483 template <class _Dummy>
484 void _STLP_CALL
_Verify(const __owned_list * __l)485 __stl_debug_engine<_Dummy>::_Verify(const __owned_list* __l) {
486 _STLP_ACQUIRE_LOCK(__l->_M_lock);
487 if (__l) {
488 _STLP_ASSERT(__l->_M_node._Owner() != 0)
489 for (__owned_link* __pos = (__owned_link*)__l->_M_node._M_next;
490 __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
491 _STLP_ASSERT(__pos->_Owner()== __l)
492 }
493 }
494 _STLP_RELEASE_LOCK(__l->_M_lock);
495 }
496
497 template <class _Dummy>
498 void _STLP_CALL
_Swap_owners(__owned_list & __x,__owned_list & __y)499 __stl_debug_engine<_Dummy>::_Swap_owners(__owned_list& __x, __owned_list& __y) {
500 /*
501 * according to the standard : --no swap() function invalidates any references,
502 * pointers, or iterators referring to the elements of the containers being swapped.
503 */
504
505 __owned_link* __tmp;
506
507 /*
508 * boris : there is a deadlock potential situation here if we lock two containers sequentially.
509 * As user is supposed to provide its own synchronization around swap() ( it is unsafe to do any container/iterator access
510 * in parallel with swap()), we just do not use any locking at all -- that behaviour is closer to non-debug version
511 */
512
513 __tmp = __x._M_node._M_next;
514
515 _Stamp_all(&__x, &__y);
516 _Stamp_all(&__y, &__x);
517
518 __x._M_node._M_next = __y._M_node._M_next;
519 __y._M_node._M_next = __tmp;
520 }
521
522 template <class _Dummy>
523 void _STLP_CALL
_Set_owner(__owned_list & __src,__owned_list & __dst)524 __stl_debug_engine<_Dummy>::_Set_owner(__owned_list& __src, __owned_list& __dst) {
525 if (&__src == &__dst)
526 return;
527
528 // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
529 typedef __owned_link _L_type;
530 _L_type* __prev = &__src._M_node;
531 _L_type* __pos = __prev->_M_next;
532
533 while (__pos != 0) {
534 __pos->_M_owner = &__dst;
535 __prev = __pos;
536 __pos = __prev->_M_next;
537 }
538 __prev->_M_next = __dst._M_node._M_next;
539 __dst._M_node._M_next = __src._M_node._M_next;
540 __src._M_node._M_next = 0;
541 }
542
543 template <class _Dummy>
544 void _STLP_CALL
_M_detach(__owned_list * __l,__owned_link * __c_node)545 __stl_debug_engine<_Dummy>::_M_detach(__owned_list* __l, __owned_link* __c_node) {
546 if (__l != 0) {
547
548 _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
549
550 _STLP_ACQUIRE_LOCK(__l->_M_lock)
551 // boris : re-test the condition in case someone else already deleted us
552 if(__c_node->_M_owner != 0) {
553 __owned_link* __prev, *__next;
554
555 for (__prev = &__l->_M_node; (__next = __prev->_M_next) != __c_node;
556 __prev = __next) {
557 _STLP_ASSERT(__next && __next->_Owner() == __l)
558 }
559
560 __prev->_M_next = __c_node->_M_next;
561 __c_node->_M_owner=0;
562 }
563 _STLP_RELEASE_LOCK(__l->_M_lock)
564 }
565 }
566
567 template <class _Dummy>
568 void _STLP_CALL
_M_attach(__owned_list * __l,__owned_link * __c_node)569 __stl_debug_engine<_Dummy>::_M_attach(__owned_list* __l, __owned_link* __c_node) {
570 if (__l ==0) {
571 (__c_node)->_M_owner = 0;
572 } else {
573 _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
574 _STLP_ACQUIRE_LOCK(__l->_M_lock)
575 __c_node->_M_owner = __l;
576 __c_node->_M_next = __l->_M_node._M_next;
577 __l->_M_node._M_next = __c_node;
578 _STLP_RELEASE_LOCK(__l->_M_lock)
579 }
580 }
581
582 template <class _Dummy>
583 void* _STLP_CALL
_Get_container_ptr(const __owned_link * __l)584 __stl_debug_engine<_Dummy>::_Get_container_ptr(const __owned_link* __l) {
585 const __owned_list* __owner = __l->_Owner();
586 _STLP_VERBOSE_RETURN_0(__owner != 0, _StlMsg_INVALID_ITERATOR)
587 void* __ret = __CONST_CAST(void*,__owner->_Owner());
588 _STLP_VERBOSE_RETURN_0(__ret !=0, _StlMsg_INVALID_CONTAINER)
589 return __ret;
590 }
591
592 template <class _Dummy>
593 bool _STLP_CALL
_Check_same_owner(const __owned_link & __i1,const __owned_link & __i2)594 __stl_debug_engine<_Dummy>::_Check_same_owner(const __owned_link& __i1,
595 const __owned_link& __i2) {
596 _STLP_VERBOSE_RETURN(__i1._Valid(), _StlMsg_INVALID_LEFTHAND_ITERATOR)
597 _STLP_VERBOSE_RETURN(__i2._Valid(), _StlMsg_INVALID_RIGHTHAND_ITERATOR)
598 _STLP_VERBOSE_RETURN((__i1._Owner() == __i2._Owner()), _StlMsg_DIFFERENT_OWNERS)
599 return true;
600 }
601
602 template <class _Dummy>
603 bool _STLP_CALL
_Check_same_or_null_owner(const __owned_link & __i1,const __owned_link & __i2)604 __stl_debug_engine<_Dummy>::_Check_same_or_null_owner(const __owned_link& __i1,
605 const __owned_link& __i2) {
606 _STLP_VERBOSE_RETURN(__i1._Owner() == __i2._Owner(), _StlMsg_DIFFERENT_OWNERS)
607 return true;
608 }
609
610 template <class _Dummy>
611 bool _STLP_CALL
_Check_if_owner(const __owned_list * __l,const __owned_link & __it)612 __stl_debug_engine<_Dummy>::_Check_if_owner( const __owned_list * __l, const __owned_link& __it) {
613 const __owned_list* __owner_ptr = __it._Owner();
614 _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
615 _STLP_VERBOSE_RETURN(__l == __owner_ptr, _StlMsg_NOT_OWNER)
616 return true;
617 }
618
619 template <class _Dummy>
620 bool _STLP_CALL
_Check_if_not_owner(const __owned_list * __l,const __owned_link & __it)621 __stl_debug_engine<_Dummy>::_Check_if_not_owner( const __owned_list * __l, const __owned_link& __it) {
622 const __owned_list* __owner_ptr = __it._Owner();
623 _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
624 _STLP_VERBOSE_RETURN(__l != __owner_ptr, _StlMsg_SHOULD_NOT_OWNER)
625 return true;
626 }
627
628 _STLP_MOVE_TO_STD_NAMESPACE
629 _STLP_END_NAMESPACE
630
631 # endif /* _STLP_DEBUG */
632
633 #endif /* if defined (EXPOSE_GLOBALS_IMPLEMENTATION) */
634
635 #endif /* header guard */
636
637 // Local Variables:
638 // mode:C++
639 // End:
640