]> git.buserror.net Git - polintos/scott/priv.git/blob - include/c++/stl/stl/debug/_debug.c
minor doc updates
[polintos/scott/priv.git] / include / c++ / stl / stl / debug / _debug.c
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
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)
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
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>
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>
85 bool _STLP_CALL __check_range_aux(_Integral /*__first*/, _Integral /*__last*/,
86                                   const __true_type& /*_IsIntegral*/)
87 { return true; }
88
89 template <class _Iterator>
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>
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>
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>
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>
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>
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>
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>
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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: