Home | History | Annotate | Download | only in debug
      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 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)
     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
     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>
     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(stlp_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(stlp_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         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>
    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         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>
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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