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
stlp_in_range_aux(const _Iterator & __it,const _Iterator & __first,const _Iterator & __last,const random_access_iterator_tag &)47 stlp_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_in_range_aux(_Iterator1 __it,const _Iterator & __first,const _Iterator & __last,const forward_iterator_tag &)56 inline bool _STLP_CALL  stlp_in_range_aux(_Iterator1 __it, const _Iterator& __first,
57 #else
58 inline bool _STLP_CALL  stlp_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
stlp_in_range_aux(const _Iterator1 & __it,const _Iterator & __first,const _Iterator & __last,const bidirectional_iterator_tag &)69 stlp_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(stlp_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(stlp_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         stlp_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         stlp_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 
200 #if defined(_STLP_WCE) && defined(_ARM_)
201   // Note: This part is needed for compiling under Windows CE under ARM and correctly using
202   // _STLP_DEBUG mode. This comes from a bug in the ARM compiler where checked iterators that
203   // are passed by value are not copied over correctly. When __change_range_owner is called,
204   // e.g. in std::list::splice() the wrong _M_owner field gets modified and the __first
205   // iterator has the old _M_owner field, but was moved to the new __owned_list. Setting
206   // the first iterator's _M_owner field fixes this. Ugly but works.
207   __pos = __CONST_CAST(_Iterator*, &__first);
208   __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
209 #endif
210   //_STLP_RELEASE_LOCK(__base->_M_lock)
211 }
212 
213 template <class _Iterator>
__change_ite_owner(const _Iterator & __it,const __owned_list * __dst)214 void _STLP_CALL __change_ite_owner(const _Iterator& __it,
215                                    const __owned_list* __dst) {
216   if (__it._Owner() == __dst)
217     return;
218 
219   typedef __owned_link _L_type;
220   // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
221   //_STLP_ACQUIRE_LOCK(__base->_M_lock)
222   __owned_list *__base = __CONST_CAST(__owned_list*, __it._Owner());
223   _L_type* __prev = &__base->_M_node;
224   _L_type* __pos = __prev->_M_next;
225   _L_type* __dst_prev = __CONST_CAST(_L_type*, &__dst->_M_node);
226 
227   while (__pos != 0) {
228     // this requires safe iterators to be derived from __owned_link
229     if ((__pos != __STATIC_CAST(const _L_type*, &__it)) &&
230         (__STATIC_CAST(_Iterator*, __pos)->_M_iterator == __it._M_iterator)) {
231       __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
232       //remove __pos from __base:
233       __prev->_M_next = __pos->_M_next;
234       //add __pos to __dst:
235       __pos->_M_next = __dst_prev->_M_next;
236       __dst_prev->_M_next = __pos;
237     }
238     else {
239       __prev = __pos;
240     }
241     __pos = __prev->_M_next;
242   }
243   //_STLP_RELEASE_LOCK(__base->_M_lock)
244 }
245 
246 _STLP_MOVE_TO_STD_NAMESPACE
247 _STLP_END_NAMESPACE
248 
249 #endif /* _STLP_DEBUG */
250 
251 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
252 
253 #  ifndef _STLP_INTERNAL_CSTDLIB
254 #    include <stl/_cstdlib.h>
255 #  endif
256 
257 //==========================================================
258 // .c section
259 //  owned_list non-inline methods and global functions
260 //==========================================================
261 
262 #  if defined (_STLP_ASSERTIONS)
263 
264 _STLP_BEGIN_NAMESPACE
265 _STLP_MOVE_TO_PRIV_NAMESPACE
266 
267 #    if !defined (_STLP_STRING_LITERAL)
268 #      define _STLP_STRING_LITERAL(__x) __x
269 #    endif
270 
271 #    if defined (_STLP_USE_WIDE_INTERFACE)
272 // note: WinCE needs this to format single-byte strings in __stl_debug_engine::_Message
273 #      define _STLP_PERCENT_S "%hs"
274 #    else
275 #      define _STLP_PERCENT_S "%s"
276 #    endif /* _STLP_USE_WIDE_INTERFACE */
277 
278 #    define _STLP_MESSAGE_TABLE_BODY = { \
279 _STLP_STRING_LITERAL("\n" _STLP_PERCENT_S "(%d): STL error: " _STLP_PERCENT_S "\n"), \
280 _STLP_STRING_LITERAL(_STLP_PERCENT_S "(%d): STL assertion failure : " _STLP_PERCENT_S "\n" _STLP_ASSERT_MSG_TRAILER), \
281 _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), \
282 _STLP_STRING_LITERAL("Invalid argument to operation (see operation documentation)"),                  \
283 _STLP_STRING_LITERAL("Taking an iterator out of destroyed (or otherwise corrupted) container"),       \
284 _STLP_STRING_LITERAL("Trying to extract an object out from empty container"),\
285 _STLP_STRING_LITERAL("Past-the-end iterator could not be erased"),  \
286 _STLP_STRING_LITERAL("Index out of bounds"),  \
287 _STLP_STRING_LITERAL("Container doesn't own the iterator"),  \
288 _STLP_STRING_LITERAL("Container is owner of the iterator, but should not"),  \
289 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) iterator used"),  \
290 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) lefthand iterator in expression"),  \
291 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) righthand iterator in expression"),  \
292 _STLP_STRING_LITERAL("Iterators used in expression are from different owners"),  \
293 _STLP_STRING_LITERAL("Iterator could not be dereferenced (past-the-end ?)"),  \
294 _STLP_STRING_LITERAL("Range [first,last) is invalid"),  \
295 _STLP_STRING_LITERAL("Iterator is not in range [first,last)"),  \
296 _STLP_STRING_LITERAL("Range [first,last) is not in range [start,finish)"),  \
297 _STLP_STRING_LITERAL("The advance would produce invalid iterator"),  \
298 _STLP_STRING_LITERAL("Iterator is singular (advanced beyond the bounds ?)"),  \
299 _STLP_STRING_LITERAL("Invalid strict weak ordering predicate, if pred(a, b) then we should have !pred(b, a)"), \
300 _STLP_STRING_LITERAL("Invalid equivalent predicate, if pred(a, b) then we should have pred(b, a)"), \
301 _STLP_STRING_LITERAL("Memory block deallocated twice"),  \
302 _STLP_STRING_LITERAL("Deallocating a block that was never allocated"),  \
303 _STLP_STRING_LITERAL("Deallocating a memory block allocated for another type"),  \
304 _STLP_STRING_LITERAL("Size of block passed to deallocate() doesn't match block size"),  \
305 _STLP_STRING_LITERAL("Pointer underrun - safety margin at front of memory block overwritten"),  \
306 _STLP_STRING_LITERAL("Pointer overrrun - safety margin at back of memory block overwritten"),   \
307 _STLP_STRING_LITERAL("Attempt to dereference null pointer returned by auto_ptr::get()"),   \
308 _STLP_STRING_LITERAL("Memory allocation function returned a wrongly align memory block"),   \
309 _STLP_STRING_LITERAL("Unknown problem") \
310   }
311 
312 template <class _Dummy>
313 const char* __stl_debug_engine<_Dummy>::_Message_table[_StlMsg_MAX] _STLP_MESSAGE_TABLE_BODY;
314 
315 #    undef _STLP_STRING_LITERAL
316 #    undef _STLP_PERCENT_S
317 
318 _STLP_MOVE_TO_STD_NAMESPACE
319 _STLP_END_NAMESPACE
320 
321 #  if !defined (_STLP_DEBUG_MESSAGE)
322 #    ifndef _STLP_INTERNAL_CSTDARG
323 #      include <stl/_cstdarg.h>
324 #    endif
325 #    ifndef _STLP_INTERNAL_CSTDIO
326 #      include <stl/_cstdio.h>
327 #    endif
328 #    if defined (_STLP_DEBUG_MODE_THROWS) && !defined (_STLP_RANGE_ERRORS_H)
329 #      include <stl/_range_errors.h>
330 #    endif
331 
332 _STLP_BEGIN_NAMESPACE
333 _STLP_MOVE_TO_PRIV_NAMESPACE
334 
335 template <class _Dummy>
336 void _STLP_CALL
_Message(const char * __format_str,...)337 __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...) {
338   STLPORT_CSTD::va_list __args;
339   va_start( __args, __format_str );
340 
341 #      if !defined (_STLP_DEBUG_MODE_THROWS)
342 #        if defined (_STLP_USE_WIDE_INTERFACE)
343   TCHAR __buffer[512];
344   int _convert = strlen(__format_str) + 1;
345   LPWSTR _lpw = (LPWSTR)alloca(_convert * sizeof(wchar_t));
346   _lpw[0] = '\0';
347   MultiByteToWideChar(GetACP(), 0, __format_str, -1, _lpw, _convert);
348   wvsprintf(__buffer, _lpw, __args);
349   _STLP_WINCE_TRACE(__buffer);
350 #        elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
351   char __buffer [4096];
352 
353 #          if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
354   vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
355 #          else
356   vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
357 #          endif
358 
359   OutputDebugStringA(__buffer);
360 
361 #        elif defined (__amigaos__)
362   STLPORT_CSTD::vfprintf(stderr, __format_str, (char *)__args);
363 #        else
364   STLPORT_CSTD::vfprintf(stderr, __format_str, __args);
365 #        endif
366 #      else
367   char __buffer[4096];
368 
369 #        if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
370   vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
371 #        elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
372   vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
373 #        else
374   vsprintf(__buffer, __format_str, __args);
375 #        endif
376 #      endif
377 
378 #      ifdef _STLP_DEBUG_MESSAGE_POST
379   _STLP_DEBUG_MESSAGE_POST
380 #      endif
381 
382   va_end(__args);
383 
384 #      if defined (_STLP_DEBUG_MODE_THROWS)
385   __stl_throw_runtime_error(__buffer);
386 #      endif
387 }
388 
389 _STLP_MOVE_TO_STD_NAMESPACE
390 _STLP_END_NAMESPACE
391 
392 #    else
393 _STLP_BEGIN_NAMESPACE
394 _STLP_MOVE_TO_PRIV_NAMESPACE
395 template <class _Dummy>
396 void _STLP_CALL
397 __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...)
398 {}
399 _STLP_MOVE_TO_STD_NAMESPACE
400 _STLP_END_NAMESPACE
401 #    endif /* _STLP_DEBUG_MESSAGE */
402 
403 _STLP_BEGIN_NAMESPACE
404 _STLP_MOVE_TO_PRIV_NAMESPACE
405 
406 template <class _Dummy>
407 void _STLP_CALL
_IndexedError(int __error_ind,const char * __f,int __l)408 __stl_debug_engine<_Dummy>::_IndexedError(int __error_ind, const char* __f, int __l) {
409   __stl_debug_message(_Message_table[_StlFormat_ERROR_RETURN],
410                       __f, __l, _Message_table[__error_ind]);
411 }
412 
413 template <class _Dummy>
414 void _STLP_CALL
_VerboseAssert(const char * __expr,int __error_ind,const char * __f,int __l)415 __stl_debug_engine<_Dummy>::_VerboseAssert(const char* __expr, int __error_ind, const char* __f, int __l) {
416   __stl_debug_message(_Message_table[_StlFormat_VERBOSE_ASSERTION_FAILURE],
417                       __f, __l, _Message_table[__error_ind], __f, __l, __expr);
418   __stl_debug_terminate();
419 }
420 
421 template <class _Dummy>
422 void _STLP_CALL
_Assert(const char * __expr,const char * __f,int __l)423 __stl_debug_engine<_Dummy>::_Assert(const char* __expr, const char* __f, int __l) {
424   __stl_debug_message(_Message_table[_StlFormat_ASSERTION_FAILURE],__f, __l, __expr);
425   __stl_debug_terminate();
426 }
427 
428 // if exceptions are present, sends unique exception
429 // if not, calls abort() to terminate
430 template <class _Dummy>
431 void _STLP_CALL
_Terminate()432 __stl_debug_engine<_Dummy>::_Terminate()
433 { _STLP_ABORT(); }
434 
435 _STLP_MOVE_TO_STD_NAMESPACE
436 _STLP_END_NAMESPACE
437 
438 #  endif /* _STLP_ASSERTIONS */
439 
440 #  if defined (_STLP_DEBUG)
441 
442 _STLP_BEGIN_NAMESPACE
443 _STLP_MOVE_TO_PRIV_NAMESPACE
444 
445 //==========================================================
446 //  owned_list non-inline methods
447 //==========================================================
448 
449 template <class _Dummy>
450 void  _STLP_CALL
_Invalidate_all(__owned_list * __l)451 __stl_debug_engine<_Dummy>::_Invalidate_all(__owned_list* __l) {
452   _STLP_ACQUIRE_LOCK(__l->_M_lock);
453   _Stamp_all(__l, 0);
454   __l->_M_node._M_next =0;
455   _STLP_RELEASE_LOCK(__l->_M_lock);
456 }
457 
458 // boris : this is unasafe routine; should be used from within critical section only !
459 template <class _Dummy>
460 void  _STLP_CALL
_Stamp_all(__owned_list * __l,__owned_list * __o)461 __stl_debug_engine<_Dummy>::_Stamp_all(__owned_list* __l, __owned_list* __o) {
462   // crucial
463   if (__l->_M_node._M_owner) {
464     for (__owned_link*  __pos = (__owned_link*)__l->_M_node._M_next;
465       __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
466       _STLP_ASSERT(__pos->_Owner()== __l)
467       __pos->_M_owner=__o;
468     }
469   }
470 }
471 
472 template <class _Dummy>
473 void  _STLP_CALL
_Verify(const __owned_list * __l)474 __stl_debug_engine<_Dummy>::_Verify(const __owned_list* __l) {
475   _STLP_ACQUIRE_LOCK(__l->_M_lock);
476   if (__l) {
477     _STLP_ASSERT(__l->_M_node._Owner() != 0)
478     for (__owned_link* __pos = (__owned_link*)__l->_M_node._M_next;
479          __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
480       _STLP_ASSERT(__pos->_Owner()== __l)
481     }
482   }
483   _STLP_RELEASE_LOCK(__l->_M_lock);
484 }
485 
486 template <class _Dummy>
487 void _STLP_CALL
_Swap_owners(__owned_list & __x,__owned_list & __y)488 __stl_debug_engine<_Dummy>::_Swap_owners(__owned_list& __x, __owned_list& __y) {
489   /*
490    *  according to the standard : --no swap() function invalidates any references,
491    *  pointers,  or  iterators referring to the elements of the containers being swapped.
492    */
493 
494   __owned_link* __tmp;
495 
496   /*
497    * boris : there is a deadlock potential situation here if we lock two containers sequentially.
498    * As user is supposed to provide its own synchronization around swap() ( it is unsafe to do any container/iterator access
499    * in parallel with swap()), we just do not use any locking at all -- that behaviour is closer to non-debug version
500    */
501 
502   __tmp = __x._M_node._M_next;
503 
504   _Stamp_all(&__x, &__y);
505   _Stamp_all(&__y, &__x);
506 
507   __x._M_node._M_next = __y._M_node._M_next;
508   __y._M_node._M_next = __tmp;
509 }
510 
511 template <class _Dummy>
512 void _STLP_CALL
_Set_owner(__owned_list & __src,__owned_list & __dst)513 __stl_debug_engine<_Dummy>::_Set_owner(__owned_list& __src, __owned_list& __dst) {
514   if (&__src == &__dst)
515     return;
516 
517   // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
518   typedef __owned_link _L_type;
519   _L_type* __prev = &__src._M_node;
520   _L_type* __pos = __prev->_M_next;
521 
522   while (__pos != 0) {
523     __pos->_M_owner = &__dst;
524     __prev = __pos;
525     __pos = __prev->_M_next;
526   }
527   __prev->_M_next = __dst._M_node._M_next;
528   __dst._M_node._M_next = __src._M_node._M_next;
529   __src._M_node._M_next = 0;
530 }
531 
532 template <class _Dummy>
533 void _STLP_CALL
_M_detach(__owned_list * __l,__owned_link * __c_node)534 __stl_debug_engine<_Dummy>::_M_detach(__owned_list* __l, __owned_link* __c_node) {
535   if (__l  != 0) {
536 
537     _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
538 
539     _STLP_ACQUIRE_LOCK(__l->_M_lock)
540       // boris : re-test the condition in case someone else already deleted us
541       if(__c_node->_M_owner != 0) {
542         __owned_link* __prev, *__next;
543 
544         for (__prev = &__l->_M_node; (__next = __prev->_M_next) != __c_node;
545              __prev = __next) {
546           _STLP_ASSERT(__next && __next->_Owner() == __l)
547             }
548 
549         __prev->_M_next = __c_node->_M_next;
550         __c_node->_M_owner=0;
551       }
552     _STLP_RELEASE_LOCK(__l->_M_lock)
553   }
554 }
555 
556 template <class _Dummy>
557 void _STLP_CALL
_M_attach(__owned_list * __l,__owned_link * __c_node)558 __stl_debug_engine<_Dummy>::_M_attach(__owned_list* __l, __owned_link* __c_node) {
559   if (__l ==0) {
560     (__c_node)->_M_owner = 0;
561   } else {
562     _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
563     _STLP_ACQUIRE_LOCK(__l->_M_lock)
564     __c_node->_M_owner = __l;
565     __c_node->_M_next = __l->_M_node._M_next;
566     __l->_M_node._M_next = __c_node;
567     _STLP_RELEASE_LOCK(__l->_M_lock)
568   }
569 }
570 
571 template <class _Dummy>
572 void* _STLP_CALL
_Get_container_ptr(const __owned_link * __l)573 __stl_debug_engine<_Dummy>::_Get_container_ptr(const __owned_link* __l) {
574   const __owned_list* __owner    = __l->_Owner();
575   _STLP_VERBOSE_RETURN_0(__owner != 0, _StlMsg_INVALID_ITERATOR)
576   void* __ret = __CONST_CAST(void*,__owner->_Owner());
577   _STLP_VERBOSE_RETURN_0(__ret !=0, _StlMsg_INVALID_CONTAINER)
578   return __ret;
579 }
580 
581 template <class _Dummy>
582 bool _STLP_CALL
_Check_same_owner(const __owned_link & __i1,const __owned_link & __i2)583 __stl_debug_engine<_Dummy>::_Check_same_owner(const __owned_link& __i1,
584                                               const __owned_link& __i2) {
585   _STLP_VERBOSE_RETURN(__i1._Valid(), _StlMsg_INVALID_LEFTHAND_ITERATOR)
586   _STLP_VERBOSE_RETURN(__i2._Valid(), _StlMsg_INVALID_RIGHTHAND_ITERATOR)
587   _STLP_VERBOSE_RETURN((__i1._Owner() == __i2._Owner()), _StlMsg_DIFFERENT_OWNERS)
588   return true;
589 }
590 
591 template <class _Dummy>
592 bool _STLP_CALL
_Check_same_or_null_owner(const __owned_link & __i1,const __owned_link & __i2)593 __stl_debug_engine<_Dummy>::_Check_same_or_null_owner(const __owned_link& __i1,
594                                                       const __owned_link& __i2) {
595   _STLP_VERBOSE_RETURN(__i1._Owner() == __i2._Owner(), _StlMsg_DIFFERENT_OWNERS)
596   return true;
597 }
598 
599 template <class _Dummy>
600 bool _STLP_CALL
_Check_if_owner(const __owned_list * __l,const __owned_link & __it)601 __stl_debug_engine<_Dummy>::_Check_if_owner( const __owned_list * __l, const __owned_link& __it) {
602   const __owned_list* __owner_ptr = __it._Owner();
603   _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
604   _STLP_VERBOSE_RETURN(__l == __owner_ptr, _StlMsg_NOT_OWNER)
605   return true;
606 }
607 
608 template <class _Dummy>
609 bool _STLP_CALL
_Check_if_not_owner(const __owned_list * __l,const __owned_link & __it)610 __stl_debug_engine<_Dummy>::_Check_if_not_owner( const __owned_list * __l, const __owned_link& __it) {
611   const __owned_list* __owner_ptr = __it._Owner();
612   _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
613   _STLP_VERBOSE_RETURN(__l != __owner_ptr, _StlMsg_SHOULD_NOT_OWNER)
614   return true;
615 }
616 
617 _STLP_MOVE_TO_STD_NAMESPACE
618 _STLP_END_NAMESPACE
619 
620 #  endif /* _STLP_DEBUG */
621 
622 #endif /* if defined (EXPOSE_GLOBALS_IMPLEMENTATION) */
623 
624 #endif /* header guard */
625 
626 // Local Variables:
627 // mode:C++
628 // End:
629