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__) 45template <class _Iterator> 46inline bool _STLP_CALL 47stlp_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 54template <class _Iterator1, class _Iterator> 55#if defined (_STLP_MSVC) 56inline bool _STLP_CALL stlp_in_range_aux(_Iterator1 __it, const _Iterator& __first, 57#else 58inline 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) 67template <class _Iterator1, class _Iterator> 68inline bool _STLP_CALL 69stlp_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 77template <class _Iterator> 78bool _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 84template <class _Integral> 85bool _STLP_CALL __check_range_aux(_Integral /*__first*/, _Integral /*__last*/, 86 const __true_type& /*_IsIntegral*/) 87{ return true; } 88 89template <class _Iterator> 90bool _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 95template <class _Iterator> 96bool _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 103template <class _Iterator> 104bool _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 111template <class _Tp> 112bool _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//=============================================================== 120template <class _Iterator> 121void _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 145template <class _Iterator> 146void _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 167template <class _Iterator> 168void _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 213template <class _Iterator> 214void _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 312template <class _Dummy> 313const 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 335template <class _Dummy> 336void _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 395template <class _Dummy> 396void _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 406template <class _Dummy> 407void _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 413template <class _Dummy> 414void _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 421template <class _Dummy> 422void _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 430template <class _Dummy> 431void _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 449template <class _Dummy> 450void _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 ! 459template <class _Dummy> 460void _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 472template <class _Dummy> 473void _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 486template <class _Dummy> 487void _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 511template <class _Dummy> 512void _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 532template <class _Dummy> 533void _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 556template <class _Dummy> 557void _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 571template <class _Dummy> 572void* _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 581template <class _Dummy> 582bool _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 591template <class _Dummy> 592bool _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 599template <class _Dummy> 600bool _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 608template <class _Dummy> 609bool _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