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