_debug.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628
  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. #ifndef _STLP_DEBUG_C
  20. #define _STLP_DEBUG_C
  21. #if defined (_STLP_DEBUG)
  22. #if defined (_STLP_THREADS)
  23. # if !defined (_STLP_NEED_MUTABLE)
  24. # define _STLP_ACQUIRE_LOCK(_Lock) _Lock._M_acquire_lock();
  25. # define _STLP_RELEASE_LOCK(_Lock) _Lock._M_release_lock();
  26. # else
  27. # define _STLP_ACQUIRE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_acquire_lock();
  28. # define _STLP_RELEASE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_release_lock();
  29. # endif /* _STLP_NEED_MUTABLE */
  30. #else
  31. # define _STLP_ACQUIRE_LOCK(_Lock)
  32. # define _STLP_RELEASE_LOCK(_Lock)
  33. #endif /* _STLP_THREADS */
  34. _STLP_BEGIN_NAMESPACE
  35. _STLP_MOVE_TO_PRIV_NAMESPACE
  36. //==========================================================
  37. // global non-inline functions
  38. //==========================================================
  39. // [ i1, i2)
  40. #if !defined (__DMC__)
  41. template <class _Iterator>
  42. inline bool _STLP_CALL
  43. stlp_in_range_aux(const _Iterator& __it, const _Iterator& __first,
  44. const _Iterator& __last, const random_access_iterator_tag &) {
  45. return ( __it >= __first &&
  46. __it < __last);
  47. }
  48. #endif
  49. template <class _Iterator1, class _Iterator>
  50. #if defined (_STLP_MSVC)
  51. inline bool _STLP_CALL stlp_in_range_aux(_Iterator1 __it, const _Iterator& __first,
  52. #else
  53. inline bool _STLP_CALL stlp_in_range_aux(const _Iterator1& __it, const _Iterator& __first,
  54. #endif
  55. const _Iterator& __last, const forward_iterator_tag &) {
  56. _Iterator1 __i(__first);
  57. for (; __i != __last && __i != __it; ++__i);
  58. return (__i != __last);
  59. }
  60. #if defined (_STLP_NONTEMPL_BASE_MATCH_BUG)
  61. template <class _Iterator1, class _Iterator>
  62. inline bool _STLP_CALL
  63. stlp_in_range_aux(const _Iterator1& __it, const _Iterator& __first,
  64. const _Iterator& __last, const bidirectional_iterator_tag &) {
  65. _Iterator1 __i(__first);
  66. for (; __i != __last && __i != __it; ++__i);
  67. return (__i != __last);
  68. }
  69. #endif
  70. template <class _Iterator>
  71. bool _STLP_CALL __check_range_aux(const _Iterator& __first, const _Iterator& __last,
  72. const __false_type& /*_IsIntegral*/) {
  73. _STLP_VERBOSE_RETURN(__valid_range(__first,__last), _StlMsg_INVALID_RANGE )
  74. return true;
  75. }
  76. template <class _Integral>
  77. bool _STLP_CALL __check_range_aux(_Integral /*__first*/, _Integral /*__last*/,
  78. const __true_type& /*_IsIntegral*/)
  79. { return true; }
  80. template <class _Iterator>
  81. bool _STLP_CALL __check_range(const _Iterator& __first, const _Iterator& __last) {
  82. typedef typename _IsIntegral<_Iterator>::_Ret _Integral;
  83. return __check_range_aux(__first, __last, _Integral());
  84. }
  85. template <class _Iterator>
  86. bool _STLP_CALL __check_range(const _Iterator& __it,
  87. const _Iterator& __start, const _Iterator& __finish) {
  88. _STLP_VERBOSE_RETURN(stlp_in_range(__it, __start, __finish),
  89. _StlMsg_NOT_IN_RANGE_1)
  90. return true;
  91. }
  92. template <class _Iterator>
  93. bool _STLP_CALL __check_range(const _Iterator& __first, const _Iterator& __last,
  94. const _Iterator& __start, const _Iterator& __finish) {
  95. _STLP_VERBOSE_RETURN(stlp_in_range(__first, __last, __start, __finish),
  96. _StlMsg_NOT_IN_RANGE_2)
  97. return true;
  98. }
  99. template <class _Tp>
  100. bool _STLP_CALL __check_ptr_range(const _Tp* __first, const _Tp* __last) {
  101. _STLP_VERBOSE_RETURN((__first != 0 || __last == 0), _StlMsg_INVALID_ARGUMENT)
  102. _STLP_VERBOSE_RETURN(__valid_range(__first, __last, random_access_iterator_tag()),
  103. _StlMsg_INVALID_RANGE)
  104. return true;
  105. }
  106. //===============================================================
  107. template <class _Iterator>
  108. void _STLP_CALL __invalidate_range(const __owned_list* __base,
  109. const _Iterator& __first,
  110. const _Iterator& __last) {
  111. typedef __owned_link _L_type;
  112. _STLP_ACQUIRE_LOCK(__base->_M_lock)
  113. _L_type* __prev = __CONST_CAST(_L_type*, &__base->_M_node);
  114. _L_type* __pos = __prev->_M_next;
  115. while (__pos != 0) {
  116. if (!(&__first == __STATIC_CAST(_Iterator*, __pos) || &__last == __STATIC_CAST(_Iterator*, __pos)) &&
  117. stlp_in_range_aux(__STATIC_CAST(_Iterator*, __pos)->_M_iterator,
  118. __first._M_iterator, __last._M_iterator,
  119. _STLP_ITERATOR_CATEGORY(__first, _Iterator))) {
  120. __pos->_M_owner = 0;
  121. __prev->_M_next = __pos->_M_next;
  122. }
  123. else {
  124. __prev = __pos;
  125. }
  126. __pos = __prev->_M_next;
  127. }
  128. _STLP_RELEASE_LOCK(__base->_M_lock)
  129. }
  130. template <class _Iterator>
  131. void _STLP_CALL __invalidate_iterator(const __owned_list* __base,
  132. const _Iterator& __it) {
  133. typedef __owned_link _L_type;
  134. _STLP_ACQUIRE_LOCK(__base->_M_lock)
  135. _L_type* __prev = __CONST_CAST(_L_type*, &__base->_M_node);
  136. _L_type* __pos = __prev->_M_next;
  137. while (__pos != 0) {
  138. // this requires safe iterators to be derived from __owned_link
  139. if ((__pos != __STATIC_CAST(const _L_type*, &__it)) &&
  140. (__STATIC_CAST(_Iterator*, __pos)->_M_iterator == __it._M_iterator)) {
  141. __pos->_M_owner = 0;
  142. __prev->_M_next = __pos->_M_next;
  143. }
  144. else {
  145. __prev = __pos;
  146. }
  147. __pos = __prev->_M_next;
  148. }
  149. _STLP_RELEASE_LOCK(__base->_M_lock)
  150. }
  151. template <class _Iterator>
  152. void _STLP_CALL __change_range_owner(const _Iterator& __first,
  153. const _Iterator& __last,
  154. const __owned_list* __dst) {
  155. if (__first._Owner() == __dst)
  156. return;
  157. typedef __owned_link _L_type;
  158. // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
  159. //_STLP_ACQUIRE_LOCK(__base->_M_lock)
  160. __owned_list *__base = __CONST_CAST(__owned_list*, __first._Owner());
  161. _L_type* __src_prev = &__base->_M_node;
  162. _L_type* __pos = __src_prev->_M_next;
  163. _L_type* __dst_prev = __CONST_CAST(_L_type*, &__dst->_M_node);
  164. while (__pos != 0) {
  165. if (!(&__first == __STATIC_CAST(_Iterator*, __pos) || &__last == __STATIC_CAST(_Iterator*, __pos)) &&
  166. stlp_in_range_aux(__STATIC_CAST(_Iterator*, __pos)->_M_iterator,
  167. __first._M_iterator, __last._M_iterator,
  168. _STLP_ITERATOR_CATEGORY(__first, _Iterator))) {
  169. __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
  170. //remove __pos from __base:
  171. __src_prev->_M_next = __pos->_M_next;
  172. //add __pos to __dst:
  173. __pos->_M_next = __dst_prev->_M_next;
  174. __dst_prev->_M_next = __pos;
  175. }
  176. else {
  177. __src_prev = __pos;
  178. }
  179. __pos = __src_prev->_M_next;
  180. }
  181. #if defined(_STLP_WCE) && defined(_ARM_)
  182. // Note: This part is needed for compiling under Windows CE under ARM and correctly using
  183. // _STLP_DEBUG mode. This comes from a bug in the ARM compiler where checked iterators that
  184. // are passed by value are not copied over correctly. When __change_range_owner is called,
  185. // e.g. in std::list::splice() the wrong _M_owner field gets modified and the __first
  186. // iterator has the old _M_owner field, but was moved to the new __owned_list. Setting
  187. // the first iterator's _M_owner field fixes this. Ugly but works.
  188. __pos = __CONST_CAST(_Iterator*, &__first);
  189. __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
  190. #endif
  191. //_STLP_RELEASE_LOCK(__base->_M_lock)
  192. }
  193. template <class _Iterator>
  194. void _STLP_CALL __change_ite_owner(const _Iterator& __it,
  195. const __owned_list* __dst) {
  196. if (__it._Owner() == __dst)
  197. return;
  198. typedef __owned_link _L_type;
  199. // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
  200. //_STLP_ACQUIRE_LOCK(__base->_M_lock)
  201. __owned_list *__base = __CONST_CAST(__owned_list*, __it._Owner());
  202. _L_type* __prev = &__base->_M_node;
  203. _L_type* __pos = __prev->_M_next;
  204. _L_type* __dst_prev = __CONST_CAST(_L_type*, &__dst->_M_node);
  205. while (__pos != 0) {
  206. // this requires safe iterators to be derived from __owned_link
  207. if ((__pos != __STATIC_CAST(const _L_type*, &__it)) &&
  208. (__STATIC_CAST(_Iterator*, __pos)->_M_iterator == __it._M_iterator)) {
  209. __pos->_M_owner = __CONST_CAST(__owned_list*, __dst);
  210. //remove __pos from __base:
  211. __prev->_M_next = __pos->_M_next;
  212. //add __pos to __dst:
  213. __pos->_M_next = __dst_prev->_M_next;
  214. __dst_prev->_M_next = __pos;
  215. }
  216. else {
  217. __prev = __pos;
  218. }
  219. __pos = __prev->_M_next;
  220. }
  221. //_STLP_RELEASE_LOCK(__base->_M_lock)
  222. }
  223. _STLP_MOVE_TO_STD_NAMESPACE
  224. _STLP_END_NAMESPACE
  225. #endif /* _STLP_DEBUG */
  226. #if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
  227. # ifndef _STLP_INTERNAL_CSTDLIB
  228. # include <stl/_cstdlib.h>
  229. # endif
  230. //==========================================================
  231. // .c section
  232. // owned_list non-inline methods and global functions
  233. //==========================================================
  234. # if defined (_STLP_ASSERTIONS)
  235. _STLP_BEGIN_NAMESPACE
  236. _STLP_MOVE_TO_PRIV_NAMESPACE
  237. # if !defined (_STLP_STRING_LITERAL)
  238. # define _STLP_STRING_LITERAL(__x) __x
  239. # endif
  240. # if defined (_STLP_USE_WIDE_INTERFACE)
  241. // note: WinCE needs this to format single-byte strings in __stl_debug_engine::_Message
  242. # define _STLP_PERCENT_S "%hs"
  243. # else
  244. # define _STLP_PERCENT_S "%s"
  245. # endif /* _STLP_USE_WIDE_INTERFACE */
  246. # define _STLP_MESSAGE_TABLE_BODY = { \
  247. _STLP_STRING_LITERAL("\n" _STLP_PERCENT_S "(%d): STL error: " _STLP_PERCENT_S "\n"), \
  248. _STLP_STRING_LITERAL(_STLP_PERCENT_S "(%d): STL assertion failure : " _STLP_PERCENT_S "\n" _STLP_ASSERT_MSG_TRAILER), \
  249. _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), \
  250. _STLP_STRING_LITERAL("Invalid argument to operation (see operation documentation)"), \
  251. _STLP_STRING_LITERAL("Taking an iterator out of destroyed (or otherwise corrupted) container"), \
  252. _STLP_STRING_LITERAL("Trying to extract an object out from empty container"),\
  253. _STLP_STRING_LITERAL("Past-the-end iterator could not be erased"), \
  254. _STLP_STRING_LITERAL("Index out of bounds"), \
  255. _STLP_STRING_LITERAL("Container doesn't own the iterator"), \
  256. _STLP_STRING_LITERAL("Container is owner of the iterator, but should not"), \
  257. _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) iterator used"), \
  258. _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) lefthand iterator in expression"), \
  259. _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) righthand iterator in expression"), \
  260. _STLP_STRING_LITERAL("Iterators used in expression are from different owners"), \
  261. _STLP_STRING_LITERAL("Iterator could not be dereferenced (past-the-end ?)"), \
  262. _STLP_STRING_LITERAL("Range [first,last) is invalid"), \
  263. _STLP_STRING_LITERAL("Iterator is not in range [first,last)"), \
  264. _STLP_STRING_LITERAL("Range [first,last) is not in range [start,finish)"), \
  265. _STLP_STRING_LITERAL("The advance would produce invalid iterator"), \
  266. _STLP_STRING_LITERAL("Iterator is singular (advanced beyond the bounds ?)"), \
  267. _STLP_STRING_LITERAL("Invalid strict weak ordering predicate, if pred(a, b) then we should have !pred(b, a)"), \
  268. _STLP_STRING_LITERAL("Invalid equivalent predicate, if pred(a, b) then we should have pred(b, a)"), \
  269. _STLP_STRING_LITERAL("Memory block deallocated twice"), \
  270. _STLP_STRING_LITERAL("Deallocating a block that was never allocated"), \
  271. _STLP_STRING_LITERAL("Deallocating a memory block allocated for another type"), \
  272. _STLP_STRING_LITERAL("Size of block passed to deallocate() doesn't match block size"), \
  273. _STLP_STRING_LITERAL("Pointer underrun - safety margin at front of memory block overwritten"), \
  274. _STLP_STRING_LITERAL("Pointer overrrun - safety margin at back of memory block overwritten"), \
  275. _STLP_STRING_LITERAL("Attempt to dereference null pointer returned by auto_ptr::get()"), \
  276. _STLP_STRING_LITERAL("Memory allocation function returned a wrongly align memory block"), \
  277. _STLP_STRING_LITERAL("Unknown problem") \
  278. }
  279. template <class _Dummy>
  280. const char* __stl_debug_engine<_Dummy>::_Message_table[_StlMsg_MAX] _STLP_MESSAGE_TABLE_BODY;
  281. # undef _STLP_STRING_LITERAL
  282. # undef _STLP_PERCENT_S
  283. _STLP_MOVE_TO_STD_NAMESPACE
  284. _STLP_END_NAMESPACE
  285. # if !defined (_STLP_DEBUG_MESSAGE)
  286. # ifndef _STLP_INTERNAL_CSTDARG
  287. # include <stl/_cstdarg.h>
  288. # endif
  289. # ifndef _STLP_INTERNAL_CSTDIO
  290. # include <stl/_cstdio.h>
  291. # endif
  292. # if defined (_STLP_DEBUG_MODE_THROWS) && !defined (_STLP_RANGE_ERRORS_H)
  293. # include <stl/_range_errors.h>
  294. # endif
  295. _STLP_BEGIN_NAMESPACE
  296. _STLP_MOVE_TO_PRIV_NAMESPACE
  297. template <class _Dummy>
  298. void _STLP_CALL
  299. __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...) {
  300. STLPORT_CSTD::va_list __args;
  301. va_start( __args, __format_str );
  302. # if !defined (_STLP_DEBUG_MODE_THROWS)
  303. # if defined (_STLP_USE_WIDE_INTERFACE)
  304. TCHAR __buffer[512];
  305. int _convert = strlen(__format_str) + 1;
  306. LPWSTR _lpw = (LPWSTR)alloca(_convert * sizeof(wchar_t));
  307. _lpw[0] = '\0';
  308. MultiByteToWideChar(GetACP(), 0, __format_str, -1, _lpw, _convert);
  309. wvsprintf(__buffer, _lpw, __args);
  310. _STLP_WINCE_TRACE(__buffer);
  311. # elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
  312. char __buffer [4096];
  313. # if !defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
  314. vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
  315. # else
  316. vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
  317. # endif
  318. OutputDebugStringA(__buffer);
  319. # elif defined (__amigaos__)
  320. STLPORT_CSTD::vfprintf(stderr, __format_str, (char *)__args);
  321. # else
  322. STLPORT_CSTD::vfprintf(stderr, __format_str, __args);
  323. # endif
  324. # else
  325. char __buffer[4096];
  326. # if defined (_STLP_USE_SAFE_STRING_FUNCTIONS)
  327. vsnprintf_s(__buffer, _STLP_ARRAY_SIZE(__buffer), _TRUNCATE, __format_str, __args);
  328. # elif defined (_STLP_WIN32) && (defined(_STLP_MSVC) || defined (__ICL))
  329. vsnprintf(__buffer, _STLP_ARRAY_SIZE(__buffer), __format_str, __args);
  330. # else
  331. vsprintf(__buffer, __format_str, __args);
  332. # endif
  333. # endif
  334. # ifdef _STLP_DEBUG_MESSAGE_POST
  335. _STLP_DEBUG_MESSAGE_POST
  336. # endif
  337. va_end(__args);
  338. # if defined (_STLP_DEBUG_MODE_THROWS)
  339. __stl_throw_runtime_error(__buffer);
  340. # endif
  341. }
  342. _STLP_MOVE_TO_STD_NAMESPACE
  343. _STLP_END_NAMESPACE
  344. # else
  345. _STLP_BEGIN_NAMESPACE
  346. _STLP_MOVE_TO_PRIV_NAMESPACE
  347. template <class _Dummy>
  348. void _STLP_CALL
  349. __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...)
  350. {}
  351. _STLP_MOVE_TO_STD_NAMESPACE
  352. _STLP_END_NAMESPACE
  353. # endif /* _STLP_DEBUG_MESSAGE */
  354. _STLP_BEGIN_NAMESPACE
  355. _STLP_MOVE_TO_PRIV_NAMESPACE
  356. template <class _Dummy>
  357. void _STLP_CALL
  358. __stl_debug_engine<_Dummy>::_IndexedError(int __error_ind, const char* __f, int __l) {
  359. __stl_debug_message(_Message_table[_StlFormat_ERROR_RETURN],
  360. __f, __l, _Message_table[__error_ind]);
  361. }
  362. template <class _Dummy>
  363. void _STLP_CALL
  364. __stl_debug_engine<_Dummy>::_VerboseAssert(const char* __expr, int __error_ind, const char* __f, int __l) {
  365. __stl_debug_message(_Message_table[_StlFormat_VERBOSE_ASSERTION_FAILURE],
  366. __f, __l, _Message_table[__error_ind], __f, __l, __expr);
  367. __stl_debug_terminate();
  368. }
  369. template <class _Dummy>
  370. void _STLP_CALL
  371. __stl_debug_engine<_Dummy>::_Assert(const char* __expr, const char* __f, int __l) {
  372. __stl_debug_message(_Message_table[_StlFormat_ASSERTION_FAILURE],__f, __l, __expr);
  373. __stl_debug_terminate();
  374. }
  375. // if exceptions are present, sends unique exception
  376. // if not, calls abort() to terminate
  377. template <class _Dummy>
  378. void _STLP_CALL
  379. __stl_debug_engine<_Dummy>::_Terminate()
  380. { _STLP_ABORT(); }
  381. _STLP_MOVE_TO_STD_NAMESPACE
  382. _STLP_END_NAMESPACE
  383. # endif /* _STLP_ASSERTIONS */
  384. # if defined (_STLP_DEBUG)
  385. _STLP_BEGIN_NAMESPACE
  386. _STLP_MOVE_TO_PRIV_NAMESPACE
  387. //==========================================================
  388. // owned_list non-inline methods
  389. //==========================================================
  390. template <class _Dummy>
  391. void _STLP_CALL
  392. __stl_debug_engine<_Dummy>::_Invalidate_all(__owned_list* __l) {
  393. _STLP_ACQUIRE_LOCK(__l->_M_lock);
  394. _Stamp_all(__l, 0);
  395. __l->_M_node._M_next =0;
  396. _STLP_RELEASE_LOCK(__l->_M_lock);
  397. }
  398. // boris : this is unasafe routine; should be used from within critical section only !
  399. template <class _Dummy>
  400. void _STLP_CALL
  401. __stl_debug_engine<_Dummy>::_Stamp_all(__owned_list* __l, __owned_list* __o) {
  402. // crucial
  403. if (__l->_M_node._M_owner) {
  404. for (__owned_link* __pos = (__owned_link*)__l->_M_node._M_next;
  405. __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
  406. _STLP_ASSERT(__pos->_Owner()== __l)
  407. __pos->_M_owner=__o;
  408. }
  409. }
  410. }
  411. template <class _Dummy>
  412. void _STLP_CALL
  413. __stl_debug_engine<_Dummy>::_Verify(const __owned_list* __l) {
  414. _STLP_ACQUIRE_LOCK(__l->_M_lock);
  415. if (__l) {
  416. _STLP_ASSERT(__l->_M_node._Owner() != 0)
  417. for (__owned_link* __pos = (__owned_link*)__l->_M_node._M_next;
  418. __pos != 0; __pos = (__owned_link*)__pos->_M_next) {
  419. _STLP_ASSERT(__pos->_Owner()== __l)
  420. }
  421. }
  422. _STLP_RELEASE_LOCK(__l->_M_lock);
  423. }
  424. template <class _Dummy>
  425. void _STLP_CALL
  426. __stl_debug_engine<_Dummy>::_Swap_owners(__owned_list& __x, __owned_list& __y) {
  427. /*
  428. * according to the standard : --no swap() function invalidates any references,
  429. * pointers, or iterators referring to the elements of the containers being swapped.
  430. */
  431. __owned_link* __tmp;
  432. /*
  433. * boris : there is a deadlock potential situation here if we lock two containers sequentially.
  434. * As user is supposed to provide its own synchronization around swap() ( it is unsafe to do any container/iterator access
  435. * in parallel with swap()), we just do not use any locking at all -- that behaviour is closer to non-debug version
  436. */
  437. __tmp = __x._M_node._M_next;
  438. _Stamp_all(&__x, &__y);
  439. _Stamp_all(&__y, &__x);
  440. __x._M_node._M_next = __y._M_node._M_next;
  441. __y._M_node._M_next = __tmp;
  442. }
  443. template <class _Dummy>
  444. void _STLP_CALL
  445. __stl_debug_engine<_Dummy>::_Set_owner(__owned_list& __src, __owned_list& __dst) {
  446. if (&__src == &__dst)
  447. return;
  448. // Check __stl_debug_engine<_Dummy>::_Swap_owners comments to see why there is no lock here
  449. typedef __owned_link _L_type;
  450. _L_type* __prev = &__src._M_node;
  451. _L_type* __pos = __prev->_M_next;
  452. while (__pos != 0) {
  453. __pos->_M_owner = &__dst;
  454. __prev = __pos;
  455. __pos = __prev->_M_next;
  456. }
  457. __prev->_M_next = __dst._M_node._M_next;
  458. __dst._M_node._M_next = __src._M_node._M_next;
  459. __src._M_node._M_next = 0;
  460. }
  461. template <class _Dummy>
  462. void _STLP_CALL
  463. __stl_debug_engine<_Dummy>::_M_detach(__owned_list* __l, __owned_link* __c_node) {
  464. if (__l != 0) {
  465. _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
  466. _STLP_ACQUIRE_LOCK(__l->_M_lock)
  467. // boris : re-test the condition in case someone else already deleted us
  468. if(__c_node->_M_owner != 0) {
  469. __owned_link* __prev, *__next;
  470. for (__prev = &__l->_M_node; (__next = __prev->_M_next) != __c_node;
  471. __prev = __next) {
  472. _STLP_ASSERT(__next && __next->_Owner() == __l)
  473. }
  474. __prev->_M_next = __c_node->_M_next;
  475. __c_node->_M_owner=0;
  476. }
  477. _STLP_RELEASE_LOCK(__l->_M_lock)
  478. }
  479. }
  480. template <class _Dummy>
  481. void _STLP_CALL
  482. __stl_debug_engine<_Dummy>::_M_attach(__owned_list* __l, __owned_link* __c_node) {
  483. if (__l ==0) {
  484. (__c_node)->_M_owner = 0;
  485. } else {
  486. _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
  487. _STLP_ACQUIRE_LOCK(__l->_M_lock)
  488. __c_node->_M_owner = __l;
  489. __c_node->_M_next = __l->_M_node._M_next;
  490. __l->_M_node._M_next = __c_node;
  491. _STLP_RELEASE_LOCK(__l->_M_lock)
  492. }
  493. }
  494. template <class _Dummy>
  495. void* _STLP_CALL
  496. __stl_debug_engine<_Dummy>::_Get_container_ptr(const __owned_link* __l) {
  497. const __owned_list* __owner = __l->_Owner();
  498. _STLP_VERBOSE_RETURN_0(__owner != 0, _StlMsg_INVALID_ITERATOR)
  499. void* __ret = __CONST_CAST(void*,__owner->_Owner());
  500. _STLP_VERBOSE_RETURN_0(__ret !=0, _StlMsg_INVALID_CONTAINER)
  501. return __ret;
  502. }
  503. template <class _Dummy>
  504. bool _STLP_CALL
  505. __stl_debug_engine<_Dummy>::_Check_same_owner(const __owned_link& __i1,
  506. const __owned_link& __i2) {
  507. _STLP_VERBOSE_RETURN(__i1._Valid(), _StlMsg_INVALID_LEFTHAND_ITERATOR)
  508. _STLP_VERBOSE_RETURN(__i2._Valid(), _StlMsg_INVALID_RIGHTHAND_ITERATOR)
  509. _STLP_VERBOSE_RETURN((__i1._Owner() == __i2._Owner()), _StlMsg_DIFFERENT_OWNERS)
  510. return true;
  511. }
  512. template <class _Dummy>
  513. bool _STLP_CALL
  514. __stl_debug_engine<_Dummy>::_Check_same_or_null_owner(const __owned_link& __i1,
  515. const __owned_link& __i2) {
  516. _STLP_VERBOSE_RETURN(__i1._Owner() == __i2._Owner(), _StlMsg_DIFFERENT_OWNERS)
  517. return true;
  518. }
  519. template <class _Dummy>
  520. bool _STLP_CALL
  521. __stl_debug_engine<_Dummy>::_Check_if_owner( const __owned_list * __l, const __owned_link& __it) {
  522. const __owned_list* __owner_ptr = __it._Owner();
  523. _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
  524. _STLP_VERBOSE_RETURN(__l == __owner_ptr, _StlMsg_NOT_OWNER)
  525. return true;
  526. }
  527. template <class _Dummy>
  528. bool _STLP_CALL
  529. __stl_debug_engine<_Dummy>::_Check_if_not_owner( const __owned_list * __l, const __owned_link& __it) {
  530. const __owned_list* __owner_ptr = __it._Owner();
  531. _STLP_VERBOSE_RETURN(__owner_ptr != 0, _StlMsg_INVALID_ITERATOR)
  532. _STLP_VERBOSE_RETURN(__l != __owner_ptr, _StlMsg_SHOULD_NOT_OWNER)
  533. return true;
  534. }
  535. _STLP_MOVE_TO_STD_NAMESPACE
  536. _STLP_END_NAMESPACE
  537. # endif /* _STLP_DEBUG */
  538. #endif /* if defined (EXPOSE_GLOBALS_IMPLEMENTATION) */
  539. #endif /* header guard */
  540. // Local Variables:
  541. // mode:C++
  542. // End: