/home/ntakagi/work/STLport-5.1.5/stlport/stl/debug/_debug.c

Go to the documentation of this file.
00001 /*
00002  *
00003  * Copyright (c) 1997
00004  * Moscow Center for SPARC Technology
00005  *
00006  * Copyright (c) 1999
00007  * Boris Fomitchev
00008  *
00009  * This material is provided "as is", with absolutely no warranty expressed
00010  * or implied. Any use is at your own risk.
00011  *
00012  * Permission to use or copy this software for any purpose is hereby granted
00013  * without fee, provided the above notices are retained on all copies.
00014  * Permission to modify the code and to distribute modified code is granted,
00015  * provided the above notices are retained, and a notice that the code was
00016  * modified is included with the above copyright notice.
00017  *
00018  */
00019 
00020 #ifndef _STLP_DEBUG_C
00021 #define _STLP_DEBUG_C
00022 
00023 #if defined (_STLP_DEBUG)
00024 #if defined (_STLP_THREADS)
00025 #  if !defined (_STLP_NEED_MUTABLE)
00026 #    define _STLP_ACQUIRE_LOCK(_Lock) _Lock._M_acquire_lock();
00027 #    define _STLP_RELEASE_LOCK(_Lock) _Lock._M_release_lock();
00028 #  else
00029 #    define _STLP_ACQUIRE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_acquire_lock();
00030 #    define _STLP_RELEASE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_release_lock();
00031 #  endif /* _STLP_NEED_MUTABLE */
00032 #else
00033 #  define _STLP_ACQUIRE_LOCK(_Lock)
00034 #  define _STLP_RELEASE_LOCK(_Lock)
00035 #endif /* _STLP_THREADS */
00036 
00037 _STLP_BEGIN_NAMESPACE
00038 _STLP_MOVE_TO_PRIV_NAMESPACE
00039 
00040 //==========================================================
00041 //  global non-inline functions
00042 //==========================================================
00043 // [ i1, i2)
00044 #if !defined (__DMC__)
00045 template <class _Iterator>
00046 inline bool  _STLP_CALL
00047 __in_range_aux(const _Iterator& __it, const _Iterator& __first,
00048                const _Iterator& __last, const random_access_iterator_tag &) {
00049     return ( __it >= __first &&
00050              __it < __last);
00051 }
00052 #endif
00053 
00054 template <class _Iterator1, class _Iterator>
00055 #if defined (_STLP_MSVC) && (_STLP_MSVC >= 1100)
00056 inline bool _STLP_CALL  __in_range_aux(_Iterator1 __it, const _Iterator& __first,
00057 #else
00058 inline bool _STLP_CALL  __in_range_aux(const _Iterator1& __it, const _Iterator& __first,
00059 #endif
00060                                        const _Iterator& __last, const forward_iterator_tag &) {
00061   _Iterator1 __i(__first);
00062   for (;  __i != __last && __i != __it; ++__i);
00063   return (__i != __last);
00064 }
00065 
00066 #if defined (_STLP_NONTEMPL_BASE_MATCH_BUG)
00067 template <class _Iterator1, class _Iterator>
00068 inline bool  _STLP_CALL
00069 __in_range_aux(const _Iterator1& __it, const _Iterator& __first,
00070                const _Iterator& __last, const bidirectional_iterator_tag &) {
00071   _Iterator1 __i(__first);
00072   for (;  __i != __last && __i != __it; ++__i);
00073   return (__i != __last);
00074 }
00075 #endif
00076 
00077 template <class _Iterator>
00078 bool _STLP_CALL __check_range_aux(const _Iterator& __first, const _Iterator& __last,
00079                                   const __false_type& /*_IsIntegral*/) {
00080   _STLP_VERBOSE_RETURN(__valid_range(__first,__last), _StlMsg_INVALID_RANGE )
00081   return true;
00082 }
00083 
00084 template <class _Integral>
00085 bool _STLP_CALL __check_range_aux(_Integral /*__first*/, _Integral /*__last*/,
00086                                   const __true_type& /*_IsIntegral*/)
00087 { return true; }
00088 
00089 template <class _Iterator>
00090 bool _STLP_CALL  __check_range(const _Iterator& __first, const _Iterator& __last) {
00091   typedef typename _IsIntegral<_Iterator>::_Ret _Integral;
00092   return __check_range_aux(__first, __last, _Integral());
00093 }
00094 
00095 template <class _Iterator>
00096 bool _STLP_CALL  __check_range(const _Iterator& __it,
00097                                const _Iterator& __start, const _Iterator& __finish) {
00098   _STLP_VERBOSE_RETURN(__in_range(__it, __start, __finish),
00099                        _StlMsg_NOT_IN_RANGE_1)
00100   return true;
00101 }
00102 
00103 template <class _Iterator>
00104 bool _STLP_CALL  __check_range(const _Iterator& __first, const _Iterator& __last,
00105                                const _Iterator& __start, const _Iterator& __finish) {
00106   _STLP_VERBOSE_RETURN(__in_range(__first, __last, __start, __finish),
00107                        _StlMsg_NOT_IN_RANGE_2)
00108   return true;
00109 }
00110 
00111 template <class _Tp>
00112 bool _STLP_CALL __check_ptr_range(const _Tp* __first, const _Tp* __last) {
00113   _STLP_VERBOSE_RETURN((__first != 0 || __last == 0), _StlMsg_INVALID_ARGUMENT)
00114   _STLP_VERBOSE_RETURN(__valid_range(__first, __last, random_access_iterator_tag()),
00115                        _StlMsg_INVALID_RANGE)
00116   return true;
00117 }
00118 
00119 //===============================================================
00120 template <class _Iterator>
00121 void _STLP_CALL __invalidate_range(const __owned_list* __base,
00122                                    const _Iterator& __first,
00123                                    const _Iterator& __last) {
00124   typedef __owned_link _L_type;
00125   _STLP_ACQUIRE_LOCK(__base->_M_lock)
00126   _L_type* __prev = __CONST_CAST(_L_type*, &__base->_M_node);
00127   _L_type* __pos = __prev->_M_next;
00128 
00129   while (__pos != 0) {
00130     if (!(&__first == __STATIC_CAST(_Iterator*, __pos) || &__last == __STATIC_CAST(_Iterator*, __pos)) &&
00131         __in_range_aux(__STATIC_CAST(_Iterator*, __pos)->_M_iterator,
00132                        __first._M_iterator, __last._M_iterator,
00133                        _STLP_ITERATOR_CATEGORY(__first, _Iterator))) {
00134       __pos->_M_owner = 0;
00135       __prev->_M_next = __pos->_M_next;
00136     }
00137     else {
00138       __prev = __pos;
00139     }
00140     __pos = __prev->_M_next;
00141   }
00142   _STLP_RELEASE_LOCK(__base->_M_lock)
00143 }
00144 
00145 template <class _Iterator>
00146 void _STLP_CALL __invalidate_iterator(const __owned_list* __base,
00147                                       const _Iterator& __it) {
00148   typedef __owned_link   _L_type;
00149   _STLP_ACQUIRE_LOCK(__base->_M_lock)
00150   _L_type* __prev = __CONST_CAST(_L_type*, &__base->_M_node);
00151   _L_type* __pos = __prev->_M_next;
00152   while (__pos != 0) {
00153     // this requires safe iterators to be derived from __owned_link
00154     if ((__pos != __STATIC_CAST(const _L_type*, &__it)) &&
00155         (__STATIC_CAST(_Iterator*, __pos)->_M_iterator == __it._M_iterator)) {
00156       __pos->_M_owner = 0;
00157       __prev->_M_next = __pos->_M_next;
00158     }
00159     else {
00160       __prev = __pos;
00161     }
00162     __pos = __prev->_M_next;
00163   }
00164   _STLP_RELEASE_LOCK(__base->_M_lock)
00165 }
00166 
00167 template <class _Iterator>
00168 void _STLP_CALL  __change_range_owner(const _Iterator& __first,
00169                                       const _Iterator& __last,
00170                                       const __owned_list* __dst) {
00171   if (__first._Owner() == __dst)
00172     return;
00173 
00174   typedef __owned_link _L_type;
00175   // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
00176   //_STLP_ACQUIRE_LOCK(__base->_M_lock)
00177   __owned_list *__base = __CONST_CAST(__owned_list*, __first._Owner());
00178   _L_type* __src_prev = &__base->_M_node;
00179   _L_type* __pos = __src_prev->_M_next;
00180   _L_type* __dst_prev = __CONST_CAST(_L_type*, &__dst->_M_node);
00181 
00182   while (__pos != 0) {
00183     if (!(&__first == __STATIC_CAST(_Iterator*, __pos) || &__last == __STATIC_CAST(_Iterator*, __pos)) &&
00184         __in_range_aux(__STATIC_CAST(_Iterator*, __pos)->_M_iterator,
00185                        __first._M_iterator, __last._M_iterator,
00186                        _STLP_ITERATOR_CATEGORY(__first, _Iterator))) {
00187       __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
00188       //remove __pos from __base:
00189       __src_prev->_M_next = __pos->_M_next;
00190       //add __pos to __dst:
00191       __pos->_M_next = __dst_prev->_M_next;
00192       __dst_prev->_M_next = __pos;
00193     }
00194     else {
00195       __src_prev = __pos;
00196     }
00197     __pos = __src_prev->_M_next;
00198   }
00199   //_STLP_RELEASE_LOCK(__base->_M_lock)
00200 }
00201 
00202 template <class _Iterator>
00203 void _STLP_CALL __change_ite_owner(const _Iterator& __it,
00204                                    const __owned_list* __dst) {
00205   if (__it._Owner() == __dst)
00206     return;
00207 
00208   typedef __owned_link _L_type;
00209   // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
00210   //_STLP_ACQUIRE_LOCK(__base->_M_lock)
00211   __owned_list *__base = __CONST_CAST(__owned_list*, __it._Owner());
00212   _L_type* __prev = &__base->_M_node;
00213   _L_type* __pos = __prev->_M_next;
00214   _L_type* __dst_prev = __CONST_CAST(_L_type*, &__dst->_M_node);
00215 
00216   while (__pos != 0) {
00217     // this requires safe iterators to be derived from __owned_link
00218     if ((__pos != __STATIC_CAST(const _L_type*, &__it)) &&
00219         (__STATIC_CAST(_Iterator*, __pos)->_M_iterator == __it._M_iterator)) {
00220       __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
00221       //remove __pos from __base:
00222       __prev->_M_next = __pos->_M_next;
00223       //add __pos to __dst:
00224       __pos->_M_next = __dst_prev->_M_next;
00225       __dst_prev->_M_next = __pos;
00226     }
00227     else {
00228       __prev = __pos;
00229     }
00230     __pos = __prev->_M_next;
00231   }
00232   //_STLP_RELEASE_LOCK(__base->_M_lock)
00233 }
00234 
00235 _STLP_MOVE_TO_STD_NAMESPACE
00236 _STLP_END_NAMESPACE
00237 
00238 #endif /* _STLP_DEBUG */
00239 
00240 #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
00241 
00242 #  ifndef _STLP_INTERNAL_CSTDLIB
00243 #    include <stl/_cstdlib.h>
00244 #  endif
00245 
00246 //==========================================================
00247 // .c section
00248 //  owned_list non-inline methods and global functions
00249 //==========================================================
00250 
00251 #  if defined (_STLP_ASSERTIONS)
00252 
00253 _STLP_BEGIN_NAMESPACE
00254 _STLP_MOVE_TO_PRIV_NAMESPACE
00255 
00256 #    if !defined (_STLP_STRING_LITERAL)
00257 #      define _STLP_STRING_LITERAL(__x) __x
00258 #    endif
00259 
00260 #    if defined (_STLP_USE_WIDE_INTERFACE)
00261 // note: WinCE needs this to format single-byte strings in __stl_debug_engine::_Message
00262 #      define _STLP_PERCENT_S "%hs"
00263 #    else
00264 #      define _STLP_PERCENT_S "%s"
00265 #    endif /* _STLP_USE_WIDE_INTERFACE */
00266 
00267 #    define _STLP_MESSAGE_TABLE_BODY = { \
00268 _STLP_STRING_LITERAL("\n" _STLP_PERCENT_S "(%d): STL error: " _STLP_PERCENT_S "\n"), \
00269 _STLP_STRING_LITERAL(_STLP_PERCENT_S "(%d): STL assertion failure : " _STLP_PERCENT_S "\n" _STLP_ASSERT_MSG_TRAILER), \
00270 _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), \
00271 _STLP_STRING_LITERAL("Invalid argument to operation (see operation documentation)"),                  \
00272 _STLP_STRING_LITERAL("Taking an iterator out of destroyed (or otherwise corrupted) container"),       \
00273 _STLP_STRING_LITERAL("Trying to extract an object out from empty container"),\
00274 _STLP_STRING_LITERAL("Past-the-end iterator could not be erased"),  \
00275 _STLP_STRING_LITERAL("Index out of bounds"),  \
00276 _STLP_STRING_LITERAL("Container doesn't own the iterator"),  \
00277 _STLP_STRING_LITERAL("Container is owner of the iterator, but should not"),  \
00278 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) iterator used"),  \
00279 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) lefthand iterator in expression"),  \
00280 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) righthand iterator in expression"),  \
00281 _STLP_STRING_LITERAL("Iterators used in expression are from different owners"),  \
00282 _STLP_STRING_LITERAL("Iterator could not be dereferenced (past-the-end ?)"),  \
00283 _STLP_STRING_LITERAL("Range [first,last) is invalid"),  \
00284 _STLP_STRING_LITERAL("Iterator is not in range [first,last)"),  \
00285 _STLP_STRING_LITERAL("Range [first,last) is not in range [start,finish)"),  \
00286 _STLP_STRING_LITERAL("The advance would produce invalid iterator"),  \
00287 _STLP_STRING_LITERAL("Iterator is singular (advanced beyond the bounds ?)"),  \
00288 _STLP_STRING_LITERAL("Invalid strict weak ordering predicate, if pred(a, b) then we should have !pred(b, a)"), \
00289 _STLP_STRING_LITERAL("Invalid equivalent predicate, if pred(a, b) then we should have pred(b, a)"), \
00290 _STLP_STRING_LITERAL("Memory block deallocated twice"),  \
00291 _STLP_STRING_LITERAL("Deallocating a block that was never allocated"),  \
00292 _STLP_STRING_LITERAL("Deallocating a memory block allocated for another type"),  \
00293 _STLP_STRING_LITERAL("Size of block passed to deallocate() doesn't match block size"),  \
00294 _STLP_STRING_LITERAL("Pointer underrun - safety margin at front of memory block overwritten"),  \
00295 _STLP_STRING_LITERAL("Pointer overrrun - safety margin at back of memory block overwritten"),   \
00296 _STLP_STRING_LITERAL("Attempt to dereference null pointer returned by auto_ptr::get()"),   \
00297 _STLP_STRING_LITERAL("Memory allocation function returned a wrongly align memory block"),   \
00298 _STLP_STRING_LITERAL("Unknown problem") \
00299   }
00300 
00301 #    if (_STLP_STATIC_TEMPLATE_DATA > 0)
00302 template <class _Dummy>
00303 const char* __stl_debug_engine<_Dummy>::_Message_table[_StlMsg_MAX]  _STLP_MESSAGE_TABLE_BODY;
00304 
00305 #      if (defined (__CYGWIN__) || defined (__MINGW32__)) && \
00306            defined (_STLP_USE_DYNAMIC_LIB) && !defined (__BUILDING_STLPORT)
00307 /*
00308  * Under cygwin, when STLport is used as a shared library, the id needs
00309  * to be specified as imported otherwise they will be duplicated in the
00310  * calling executable.
00311  */
00312 _STLP_TEMPLATE_NULL
00313 _STLP_DECLSPEC const char* __stl_debug_engine<bool>::_Message_table[_StlMsg_MAX];
00314 #      endif
00315 
00316 #    else
00317 __DECLARE_INSTANCE(const char*, __stl_debug_engine<bool>::_Message_table[_StlMsg_MAX],
00318                    _STLP_MESSAGE_TABLE_BODY);
00319 #    endif
00320 
00321 #    undef _STLP_STRING_LITERAL
00322 #    undef _STLP_PERCENT_S
00323 
00324 _STLP_MOVE_TO_STD_NAMESPACE
00325 _STLP_END_NAMESPACE
00326 
00327 // abort()
00328 #  ifndef _STLP_INTERNAL_CSTDLIB
00329 #    include <stl/_cstdlib.h>
00330 #  endif
00331 
00332 #  if !defined (_STLP_DEBUG_MESSAGE)
00333 #    ifndef _STLP_INTERNAL_CSTDARG
00334 #      include <stl/_cstdarg.h>
00335 #    endif
00336 #    ifndef _STLP_INTERNAL_CSTDIO
00337 #      include <stl/_cstdio.h>
00338 #    endif
00339 #    if defined (_STLP_DEBUG_MODE_THROWS) && !defined (_STLP_RANGE_ERRORS_H)
00340 #      include <stl/_range_errors.h>
00341 #    endif
00342 
00343 _STLP_BEGIN_NAMESPACE
00344 _STLP_MOVE_TO_PRIV_NAMESPACE
00345 
00346 template <class _Dummy>
00347 void _STLP_CALL
00348 __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...) {
00349   STLPORT_CSTD::va_list __args;
00350   va_start( __args, __format_str );
00351 
00352 #      if !defined (_STLP_DEBUG_MODE_THROWS)
00353 #        if defined (_STLP_USE_WIDE_INTERFACE)
00354   TCHAR __buffer[512];
00355   int _convert = strlen(__format_str) + 1;
00356   LPWSTR _lpw = (LPWSTR)alloca(_convert * sizeof(wchar_t));
00357   _lpw[0] = '\0';
00358   MultiByteToWideChar(GetACP(), 0, __format_str, -1, _lpw, _convert);
00359   wvsprintf(__buffer, _lpw, __args);
00360   _STLP_WINCE_TRACE(__buffer);
00361 #        elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
00362   char __buffer [4096];
00363 
00364 #          if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
00365   vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
00366 #          else
00367   vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
00368 #          endif
00369 
00370   OutputDebugStringA(__buffer);
00371 
00372 #        elif defined (__amigaos__)
00373   STLPORT_CSTD::vfprintf(stderr, __format_str, (char *)__args);
00374 #        else
00375   STLPORT_CSTD::vfprintf(stderr, __format_str, __args);
00376 #        endif
00377 #      else
00378   char __buffer[4096];
00379 
00380 #        if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
00381   vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
00382 #        elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
00383   vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
00384 #        else
00385   vsprintf(__buffer, __format_str, __args);
00386 #        endif
00387 #      endif
00388 
00389 #      ifdef _STLP_DEBUG_MESSAGE_POST
00390   _STLP_DEBUG_MESSAGE_POST
00391 #      endif
00392 
00393   va_end(__args);
00394 
00395 #      if defined (_STLP_DEBUG_MODE_THROWS)
00396   __stl_throw_runtime_error(__buffer);
00397 #      endif
00398 }
00399 
00400 _STLP_MOVE_TO_STD_NAMESPACE
00401 _STLP_END_NAMESPACE
00402 
00403 #    else
00404 _STLP_BEGIN_NAMESPACE
00405 _STLP_MOVE_TO_PRIV_NAMESPACE
00406 template <class _Dummy>
00407 void _STLP_CALL
00408 __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...)
00409 {}
00410 _STLP_MOVE_TO_STD_NAMESPACE
00411 _STLP_END_NAMESPACE
00412 #    endif /* _STLP_DEBUG_MESSAGE */
00413 
00414 _STLP_BEGIN_NAMESPACE
00415 _STLP_MOVE_TO_PRIV_NAMESPACE
00416 
00417 template <class _Dummy>
00418 void _STLP_CALL
00419 __stl_debug_engine<_Dummy>::_IndexedError(int __error_ind, const char* __f, int __l) {
00420   __stl_debug_message(_Message_table[_StlFormat_ERROR_RETURN],
00421                       __f, __l, _Message_table[__error_ind]);
00422 }
00423 
00424 template <class _Dummy>
00425 void _STLP_CALL
00426 __stl_debug_engine<_Dummy>::_VerboseAssert(const char* __expr, int __error_ind, const char* __f, int __l) {
00427   __stl_debug_message(_Message_table[_StlFormat_VERBOSE_ASSERTION_FAILURE],
00428                       __f, __l, _Message_table[__error_ind], __f, __l, __expr);
00429   __stl_debug_terminate();
00430 }
00431 
00432 template <class _Dummy>
00433 void _STLP_CALL
00434 __stl_debug_engine<_Dummy>::_Assert(const char* __expr, const char* __f, int __l) {
00435   __stl_debug_message(_Message_table[_StlFormat_ASSERTION_FAILURE],__f, __l, __expr);
00436   __stl_debug_terminate();
00437 }
00438 
00439 // if exceptions are present, sends unique exception
00440 // if not, calls abort() to terminate
00441 template <class _Dummy>
00442 void _STLP_CALL
00443 __stl_debug_engine<_Dummy>::_Terminate()
00444 { _STLP_ABORT(); }
00445 
00446 _STLP_MOVE_TO_STD_NAMESPACE
00447 _STLP_END_NAMESPACE
00448 
00449 #  endif /* _STLP_ASSERTIONS */
00450 
00451 #  if defined (_STLP_DEBUG)
00452 
00453 _STLP_BEGIN_NAMESPACE
00454 _STLP_MOVE_TO_PRIV_NAMESPACE
00455 
00456 //==========================================================
00457 //  owned_list non-inline methods
00458 //==========================================================
00459 
00460 template <class _Dummy>
00461 void  _STLP_CALL
00462 __stl_debug_engine<_Dummy>::_Invalidate_all(__owned_list* __l) {
00463   _STLP_ACQUIRE_LOCK(__l->_M_lock);
00464   _Stamp_all(__l, 0);
00465   __l->_M_node._M_next =0;
00466   _STLP_RELEASE_LOCK(__l->_M_lock);
00467 }
00468 
00469 // boris : this is unasafe routine; should be used from within critical section only !
00470 template <class _Dummy>
00471 void  _STLP_CALL
00472 __stl_debug_engine<_Dummy>::_Stamp_all(__owned_list* __l, __owned_list* __o) {
00473   // crucial
00474   if (__l->_M_node._M_owner) {
00475     for (__owned_link*  __pos = (__owned_link*)__l->_M_node._M_next;
00476       __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
00477       _STLP_ASSERT(__pos->_Owner()== __l)
00478       __pos->_M_owner=__o;
00479     }
00480   }
00481 }
00482 
00483 template <class _Dummy>
00484 void  _STLP_CALL
00485 __stl_debug_engine<_Dummy>::_Verify(const __owned_list* __l) {
00486   _STLP_ACQUIRE_LOCK(__l->_M_lock);
00487   if (__l) {
00488     _STLP_ASSERT(__l->_M_node._Owner() != 0)
00489     for (__owned_link* __pos = (__owned_link*)__l->_M_node._M_next;
00490          __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
00491       _STLP_ASSERT(__pos->_Owner()== __l)
00492     }
00493   }
00494   _STLP_RELEASE_LOCK(__l->_M_lock);
00495 }
00496 
00497 template <class _Dummy>
00498 void _STLP_CALL
00499 __stl_debug_engine<_Dummy>::_Swap_owners(__owned_list& __x, __owned_list& __y) {
00500   /*
00501    *  according to the standard : --no swap() function invalidates any references,
00502    *  pointers,  or  iterators referring to the elements of the containers being swapped.
00503    */
00504 
00505   __owned_link* __tmp;
00506 
00507   /*
00508    * boris : there is a deadlock potential situation here if we lock two containers sequentially.
00509    * As user is supposed to provide its own synchronization around swap() ( it is unsafe to do any container/iterator access
00510    * in parallel with swap()), we just do not use any locking at all -- that behaviour is closer to non-debug version
00511    */
00512 
00513   __tmp = __x._M_node._M_next;
00514 
00515   _Stamp_all(&__x, &__y);
00516   _Stamp_all(&__y, &__x);
00517 
00518   __x._M_node._M_next = __y._M_node._M_next;
00519   __y._M_node._M_next = __tmp;
00520 }
00521 
00522 template <class _Dummy>
00523 void _STLP_CALL
00524 __stl_debug_engine<_Dummy>::_Set_owner(__owned_list& __src, __owned_list& __dst) {
00525   if (&__src == &__dst)
00526     return;
00527 
00528   // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
00529   typedef __owned_link _L_type;
00530   _L_type* __prev = &__src._M_node;
00531   _L_type* __pos = __prev->_M_next;
00532 
00533   while (__pos != 0) {
00534     __pos->_M_owner = &__dst;
00535     __prev = __pos;
00536     __pos = __prev->_M_next;
00537   }
00538   __prev->_M_next = __dst._M_node._M_next;
00539   __dst._M_node._M_next = __src._M_node._M_next;
00540   __src._M_node._M_next = 0;
00541 }
00542 
00543 template <class _Dummy>
00544 void _STLP_CALL
00545 __stl_debug_engine<_Dummy>::_M_detach(__owned_list* __l, __owned_link* __c_node) {
00546   if (__l  != 0) {
00547 
00548     _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
00549 
00550     _STLP_ACQUIRE_LOCK(__l->_M_lock)
00551       // boris : re-test the condition in case someone else already deleted us
00552       if(__c_node->_M_owner != 0) {
00553         __owned_link* __prev, *__next;
00554 
00555         for (__prev = &__l->_M_node; (__next = __prev->_M_next) != __c_node;
00556              __prev = __next) {
00557           _STLP_ASSERT(__next && __next->_Owner() == __l)
00558             }
00559 
00560         __prev->_M_next = __c_node->_M_next;
00561         __c_node->_M_owner=0;
00562       }
00563     _STLP_RELEASE_LOCK(__l->_M_lock)
00564   }
00565 }
00566 
00567 template <class _Dummy>
00568 void _STLP_CALL
00569 __stl_debug_engine<_Dummy>::_M_attach(__owned_list* __l, __owned_link* __c_node) {
00570   if (__l ==0) {
00571     (__c_node)->_M_owner = 0;
00572   } else {
00573     _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
00574     _STLP_ACQUIRE_LOCK(__l->_M_lock)
00575     __c_node->_M_owner = __l;
00576     __c_node->_M_next = __l->_M_node._M_next;
00577     __l->_M_node._M_next = __c_node;
00578     _STLP_RELEASE_LOCK(__l->_M_lock)
00579   }
00580 }
00581 
00582 template <class _Dummy>
00583 void* _STLP_CALL
00584 __stl_debug_engine<_Dummy>::_Get_container_ptr(const __owned_link* __l) {
00585   const __owned_list* __owner    = __l->_Owner();
00586   _STLP_VERBOSE_RETURN_0(__owner != 0, _StlMsg_INVALID_ITERATOR)
00587   void* __ret = __CONST_CAST(void*,__owner->_Owner());
00588   _STLP_VERBOSE_RETURN_0(__ret !=0, _StlMsg_INVALID_CONTAINER)
00589   return __ret;
00590 }
00591 
00592 template <class _Dummy>
00593 bool _STLP_CALL
00594 __stl_debug_engine<_Dummy>::_Check_same_owner(const __owned_link& __i1,
00595                                               const __owned_link& __i2) {
00596   _STLP_VERBOSE_RETURN(__i1._Valid(), _StlMsg_INVALID_LEFTHAND_ITERATOR)
00597   _STLP_VERBOSE_RETURN(__i2._Valid(), _StlMsg_INVALID_RIGHTHAND_ITERATOR)
00598   _STLP_VERBOSE_RETURN((__i1._Owner() == __i2._Owner()), _StlMsg_DIFFERENT_OWNERS)
00599   return true;
00600 }
00601 
00602 template <class _Dummy>
00603 bool _STLP_CALL
00604 __stl_debug_engine<_Dummy>::_Check_same_or_null_owner(const __owned_link& __i1,
00605                                                       const __owned_link& __i2) {
00606   _STLP_VERBOSE_RETURN(__i1._Owner() == __i2._Owner(), _StlMsg_DIFFERENT_OWNERS)
00607   return true;
00608 }
00609 
00610 template <class _Dummy>
00611 bool _STLP_CALL
00612 __stl_debug_engine<_Dummy>::_Check_if_owner( const __owned_list * __l, const __owned_link& __it) {
00613   const __owned_list* __owner_ptr = __it._Owner();
00614   _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
00615   _STLP_VERBOSE_RETURN(__l == __owner_ptr, _StlMsg_NOT_OWNER)
00616   return true;
00617 }
00618 
00619 template <class _Dummy>
00620 bool _STLP_CALL
00621 __stl_debug_engine<_Dummy>::_Check_if_not_owner( const __owned_list * __l, const __owned_link& __it) {
00622   const __owned_list* __owner_ptr = __it._Owner();
00623   _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
00624   _STLP_VERBOSE_RETURN(__l != __owner_ptr, _StlMsg_SHOULD_NOT_OWNER)
00625   return true;
00626 }
00627 
00628 _STLP_MOVE_TO_STD_NAMESPACE
00629 _STLP_END_NAMESPACE
00630 
00631 #  endif /* _STLP_DEBUG */
00632 
00633 #endif /* if defined (EXPOSE_GLOBALS_IMPLEMENTATION) */
00634 
00635 #endif /* header guard */
00636 
00637 // Local Variables:
00638 // mode:C++
00639 // End:



Generated on Mon Mar 10 15:32:46 2008 by  doxygen 1.5.1