2 * © Portions copyright (c) 2006-2007 Nokia Corporation. All rights reserved.
5 * Moscow Center for SPARC Technology
10 * This material is provided "as is", with absolutely no warranty expressed
11 * or implied. Any use is at your own risk.
13 * Permission to use or copy this software for any purpose is hereby granted
14 * without fee, provided the above notices are retained on all copies.
15 * Permission to modify the code and to distribute modified code is granted,
16 * provided the above notices are retained, and a notice that the code was
17 * modified is included with the above copyright notice.
21 # ifndef _STLP_DEBUG_C
22 # define _STLP_DEBUG_C
24 #if defined ( _STLP_DEBUG )
27 # ifndef _STLP_NEED_MUTABLE
28 # define _STLP_ACQUIRE_LOCK(_Lock) _Lock._M_acquire_lock();
29 # define _STLP_RELEASE_LOCK(_Lock) _Lock._M_release_lock();
31 # define _STLP_ACQUIRE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_acquire_lock();
32 # define _STLP_RELEASE_LOCK(_Lock) ((_STLP_mutex&)_Lock)._M_release_lock();
33 # endif /* _STLP_NEED_MUTABLE */
35 # define _STLP_ACQUIRE_LOCK(_Lock)
36 # define _STLP_RELEASE_LOCK(_Lock)
37 # endif /* _STLP_THREADS */
41 //==========================================================
42 // global non-inline functions
43 //==========================================================
46 template <class _Iterator>
47 inline bool _STLP_CALL
48 __in_range_aux(const _Iterator& __it, const _Iterator& __first,
49 const _Iterator& __last, const random_access_iterator_tag &) {
50 return ( __it >= __first &&
54 template <class _Iterator1, class _Iterator>
55 # if defined (_STLP_MSVC) && (_STLP_MSVC >= 1100)
56 inline bool _STLP_CALL __in_range_aux(_Iterator1 __it, const _Iterator& __first,
58 inline bool _STLP_CALL __in_range_aux(const _Iterator1& __it, const _Iterator& __first,
60 const _Iterator& __last, const forward_iterator_tag &) {
61 _Iterator1 __i(__first);
62 for (; __i != __last && __i != __it; ++__i);
66 # if defined (_STLP_NONTEMPL_BASE_MATCH_BUG)
67 template <class _Iterator1, class _Iterator>
68 inline bool _STLP_CALL
69 __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);
77 template <class _Iterator>
78 bool _STLP_CALL __check_range(const _Iterator& __first, const _Iterator& __last) {
79 _STLP_VERBOSE_RETURN(__valid_range(__first,__last), _StlMsg_INVALID_RANGE )
83 template <class _Iterator>
84 bool _STLP_CALL __check_range(const _Iterator& __it,
85 const _Iterator& __start, const _Iterator& __finish) {
86 _STLP_VERBOSE_RETURN(__in_range(__it,__start, __finish),
87 _StlMsg_NOT_IN_RANGE_1)
91 template <class _Iterator>
92 bool _STLP_CALL __check_range(const _Iterator& __first, const _Iterator& __last,
93 const _Iterator& __start, const _Iterator& __finish) {
94 _STLP_VERBOSE_RETURN(__in_range(__first, __last, __start, __finish),
95 _StlMsg_NOT_IN_RANGE_2)
99 //===============================================================
101 template <class _Iterator>
102 void _STLP_CALL __invalidate_range(const __owned_list* __base,
103 const _Iterator& __first,
104 const _Iterator& __last)
106 typedef _Iterator* _Safe_iterator_ptr;
107 typedef __owned_link _L_type;
108 _STLP_ACQUIRE_LOCK(__base->_M_lock)
112 for (__prev = (_L_type*)&__base->_M_node, __pos= (_L_type*)__prev->_M_next;
114 if ((!(&__first == (_Iterator*)__pos || &__last == (_Iterator*)__pos))
116 ((_Iterator*)__pos)->_M_iterator,
119 _STLP_ITERATOR_CATEGORY(__first, _Iterator))) {
121 __pos = (_L_type*) (__prev->_M_next = __pos->_M_next);
125 __pos=(_L_type*)__pos->_M_next;
128 _STLP_RELEASE_LOCK(__base->_M_lock)
131 template <class _Iterator>
132 void _STLP_CALL __invalidate_iterator(const __owned_list* __base,
133 const _Iterator& __it)
135 typedef __owned_link _L_type;
136 _L_type* __position, *__prev;
137 _STLP_ACQUIRE_LOCK(__base->_M_lock)
138 for (__prev = (_L_type*)&__base->_M_node, __position = (_L_type*)__prev->_M_next;
140 // this requires safe iterators to be derived from __owned_link
141 if ((__position != (_L_type*)&__it) && ((_Iterator*)__position)->_M_iterator ==__it._M_iterator) {
142 __position->_M_owner = 0;
143 __position = (_L_type*) (__prev->_M_next = __position->_M_next);
147 __position=(_L_type*)__position->_M_next;
150 _STLP_RELEASE_LOCK(__base->_M_lock)
155 # endif /* _STLP_DEBUG */
157 # if defined (_STLP_EXPOSE_GLOBALS_IMPLEMENTATION)
159 // dwa 12/26/99 -- for abort
160 # if defined (_STLP_USE_NEW_C_HEADERS)
166 # if defined (_STLP_WIN32)
167 # include <stl/_threads.h>
170 //==========================================================
172 // owned_list non-inline methods and global functions
173 //==========================================================
175 #if defined ( _STLP_ASSERTIONS )
177 _STLP_BEGIN_NAMESPACE
179 # ifndef _STLP_STRING_LITERAL
180 # define _STLP_STRING_LITERAL(__x) __x
184 # define _STLP_PERCENT_S "%hs"
186 # define _STLP_PERCENT_S "%s"
189 # define _STLP_MESSAGE_TABLE_BODY = { \
190 _STLP_STRING_LITERAL("\n" _STLP_PERCENT_S "(%d): STL error: %s\n"), \
191 _STLP_STRING_LITERAL(_STLP_PERCENT_S "(%d): STL assertion failure : " _STLP_PERCENT_S "\n" _STLP_ASSERT_MSG_TRAILER), \
192 _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), \
193 _STLP_STRING_LITERAL("Invalid argument to operation (see operation documentation)"), \
194 _STLP_STRING_LITERAL("Taking an iterator out of destroyed (or otherwise corrupted) container"), \
195 _STLP_STRING_LITERAL("Trying to extract an object out from empty container"),\
196 _STLP_STRING_LITERAL("Past-the-end iterator could not be erased"), \
197 _STLP_STRING_LITERAL("Index out of bounds"), \
198 _STLP_STRING_LITERAL("Container doesn't own the iterator"), \
199 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) iterator used"), \
200 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) lefthand iterator in expression"), \
201 _STLP_STRING_LITERAL("Uninitialized or invalidated (by mutating operation) righthand iterator in expression"), \
202 _STLP_STRING_LITERAL("Iterators used in expression are from different owners"), \
203 _STLP_STRING_LITERAL("Iterator could not be dereferenced (past-the-end ?)"), \
204 _STLP_STRING_LITERAL("Range [first,last) is invalid"), \
205 _STLP_STRING_LITERAL("Iterator is not in range [first,last)"), \
206 _STLP_STRING_LITERAL("Range [first,last) is not in range [start,finish)"), \
207 _STLP_STRING_LITERAL("The advance would produce invalid iterator"), \
208 _STLP_STRING_LITERAL("Iterator is singular (advanced beyond the bounds ?)"), \
209 _STLP_STRING_LITERAL("Memory block deallocated twice"), \
210 _STLP_STRING_LITERAL("Deallocating a block that was never allocated"), \
211 _STLP_STRING_LITERAL("Deallocating a memory block allocated for another type"), \
212 _STLP_STRING_LITERAL("Size of block passed to deallocate() doesn't match block size"), \
213 _STLP_STRING_LITERAL("Pointer underrun - safety margin at front of memory block overwritten"), \
214 _STLP_STRING_LITERAL("Pointer overrrun - safety margin at back of memory block overwritten"), \
215 _STLP_STRING_LITERAL("Attempt to dereference null pointer returned by auto_ptr::get()"), \
216 _STLP_STRING_LITERAL("Unknown problem") \
219 # if ( _STLP_STATIC_TEMPLATE_DATA > 0 )
221 template <class _Dummy>
222 const char* __stl_debug_engine<_Dummy>::_Message_table[_StlMsg_MAX];// _STLP_MESSAGE_TABLE_BODY;
224 template <class _Dummy>
225 const char* __stl_debug_engine<_Dummy>::_Message_table[_StlMsg_MAX] _STLP_MESSAGE_TABLE_BODY;
229 __DECLARE_INSTANCE(const char*, __stl_debug_engine<bool>::_Message_table[_StlMsg_MAX],
230 _STLP_MESSAGE_TABLE_BODY);
234 # undef _STLP_STRING_LITERAL
235 # undef _STLP_PERCENT_S
241 # if !defined( _STLP_DEBUG_MESSAGE )
246 _STLP_BEGIN_NAMESPACE
248 template <class _Dummy>
250 __stl_debug_engine<_Dummy>::_Message(const char * __format_str, ...)
252 STLPORT_CSTD::va_list __args;
253 va_start( __args, __format_str );
255 # if defined (_STLP_WINCE)
257 int _convert = strlen(__format_str) + 1;
258 LPWSTR _lpw = (LPWSTR)alloca(_convert*sizeof(wchar_t));
260 MultiByteToWideChar(GetACP(), 0, __format_str, -1, _lpw, _convert);
261 wvsprintf(__buffer, _lpw, __args);
262 // wvsprintf(__buffer, __format_str, __args);
263 _STLP_WINCE_TRACE(__buffer);
264 # elif defined (_STLP_WIN32) && ( defined(_STLP_MSVC) || defined (__ICL) || defined (__BORLANDC__)) && ! defined (__WINS__)
265 char __buffer [4096];
266 _vsnprintf(__buffer, sizeof(__buffer) / sizeof(char),
267 __format_str, __args);
268 OutputDebugStringA(__buffer);
269 # elif defined (__amigaos__)
270 STLPORT_CSTD::vfprintf(stderr, __format_str, (char *)__args);
272 STLPORT_CSTD::vfprintf(stderr, __format_str, __args);
275 # ifdef _STLP_DEBUG_MESSAGE_POST
276 _STLP_DEBUG_MESSAGE_POST
285 # endif /* _STLP_DEBUG_MESSAGE */
288 _STLP_BEGIN_NAMESPACE
291 template <class _Dummy>
293 __stl_debug_engine<_Dummy>::_IndexedError(int __error_ind, const char* __f, int __l)
295 __stl_debug_message(_Message_table[_StlFormat_ERROR_RETURN],
296 __f, __l, _Message_table[__error_ind]);
299 template <class _Dummy>
301 __stl_debug_engine<_Dummy>::_VerboseAssert(const char* __expr, int __error_ind, const char* __f, int __l)
303 __stl_debug_message(_Message_table[_StlFormat_VERBOSE_ASSERTION_FAILURE],
304 __f, __l, _Message_table[__error_ind], __f, __l, __expr);
305 __stl_debug_terminate();
308 template <class _Dummy>
310 __stl_debug_engine<_Dummy>::_Assert(const char* __expr, const char* __f, int __l)
312 __stl_debug_message(_Message_table[_StlFormat_ASSERTION_FAILURE],__f, __l, __expr);
313 __stl_debug_terminate();
316 // if exceptions are present, sends unique exception
317 // if not, calls abort() to terminate
318 template <class _Dummy>
320 __stl_debug_engine<_Dummy>::_Terminate()
322 # ifdef _STLP_USE_NAMESPACES
323 using namespace _STLP_STD;
325 # if defined (_STLP_USE_EXCEPTIONS) && ! defined (_STLP_NO_DEBUG_EXCEPTIONS)
326 throw __stl_debug_exception();
334 # endif /* _STLP_ASSERTIONS */
338 _STLP_BEGIN_NAMESPACE
340 //==========================================================
341 // owned_list non-inline methods
342 //==========================================================
344 template <class _Dummy>
346 __stl_debug_engine<_Dummy>::_Invalidate_all(__owned_list* __l) {
347 _STLP_ACQUIRE_LOCK(__l->_M_lock);
349 __l->_M_node._M_next =0;
350 _STLP_RELEASE_LOCK(__l->_M_lock);
353 // boris : this is unasafe routine; should be used from within critical section only !
354 template <class _Dummy>
356 __stl_debug_engine<_Dummy>::_Stamp_all(__owned_list* __l, __owned_list* __o) {
358 if (__l->_M_node._M_owner) {
359 for (__owned_link* __position = (__owned_link*)__l->_M_node._M_next;
360 __position != 0; __position= (__owned_link*)__position->_M_next) {
361 _STLP_ASSERT(__position->_Owner()== __l)
362 __position->_M_owner=__o;
367 template <class _Dummy>
369 __stl_debug_engine<_Dummy>::_Verify(const __owned_list* __l) {
370 _STLP_ACQUIRE_LOCK(__l->_M_lock);
372 _STLP_ASSERT(__l->_M_node._Owner() != 0)
373 for (__owned_link* __position = (__owned_link*)__l->_M_node._M_next;
374 __position != 0; __position= (__owned_link*)__position->_M_next) {
375 _STLP_ASSERT(__position->_Owner()== __l)
378 _STLP_RELEASE_LOCK(__l->_M_lock);
381 template <class _Dummy>
383 __stl_debug_engine<_Dummy>::_Swap_owners(__owned_list& __x, __owned_list& __y) {
385 // according to the standard : --no swap() function invalidates any references,
386 // pointers, or iterators referring to the elements of the containers being swapped.
390 // boris : there is a deadlock potential situation here if we lock two containers sequentially.
391 // As user is supposed to provide its own synchronization around swap() ( it is unsafe to do any container/iterator access
392 // in parallel with swap()), we just do not use any locking at all -- that behaviour is closer to non-debug version
394 __tmp = __x._M_node._M_next;
396 _Stamp_all(&__x, &__y);
397 _Stamp_all(&__y, &__x);
399 __x._M_node._M_next = __y._M_node._M_next;
400 __y._M_node._M_next = __tmp;
404 template <class _Dummy>
406 __stl_debug_engine<_Dummy>::_M_detach(__owned_list* __l, __owned_link* __c_node) {
409 _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
411 _STLP_ACQUIRE_LOCK(__l->_M_lock)
412 // boris : re-test the condition in case someone else already deleted us
413 if(__c_node->_M_owner != 0) {
414 __owned_link* __prev, *__next;
416 for (__prev = &__l->_M_node; (__next = __prev->_M_next) != __c_node;
418 _STLP_ASSERT(__next && __next->_Owner() == __l)
421 __prev->_M_next = __c_node->_M_next;
422 __c_node->_M_owner=0;
424 _STLP_RELEASE_LOCK(__l->_M_lock)
428 template <class _Dummy>
430 __stl_debug_engine<_Dummy>::_M_attach(__owned_list* __l, __owned_link* __c_node) {
432 (__c_node)->_M_owner = 0;
434 _STLP_VERBOSE_ASSERT(__l->_Owner()!=0, _StlMsg_INVALID_CONTAINER)
435 _STLP_ACQUIRE_LOCK(__l->_M_lock)
436 __c_node->_M_owner = __l;
437 __c_node->_M_next = __l->_M_node._M_next;
438 __l->_M_node._M_next = __c_node;
439 _STLP_RELEASE_LOCK(__l->_M_lock)
444 template <class _Dummy>
446 __stl_debug_engine<_Dummy>::_Get_container_ptr(const __owned_link* __l) {
447 const __owned_list* __owner = __l->_Owner();
448 _STLP_VERBOSE_RETURN_0(__owner != 0, _StlMsg_INVALID_ITERATOR)
449 void* __ret = __CONST_CAST(void*,__owner->_Owner());
450 _STLP_VERBOSE_RETURN_0(__ret !=0, _StlMsg_INVALID_CONTAINER)
454 template <class _Dummy>
456 __stl_debug_engine<_Dummy>::_Check_same_owner( const __owned_link& __i1,
457 const __owned_link& __i2)
459 _STLP_VERBOSE_RETURN(__i1._Valid(), _StlMsg_INVALID_LEFTHAND_ITERATOR)
460 _STLP_VERBOSE_RETURN(__i2._Valid(), _StlMsg_INVALID_RIGHTHAND_ITERATOR)
461 _STLP_VERBOSE_RETURN((__i1._Owner()==__i2._Owner()), _StlMsg_DIFFERENT_OWNERS)
465 template <class _Dummy>
467 __stl_debug_engine<_Dummy>::_Check_same_owner_or_null( const __owned_link& __i1,
468 const __owned_link& __i2)
470 _STLP_VERBOSE_RETURN(__i1._Owner()==__i2._Owner(), _StlMsg_DIFFERENT_OWNERS)
474 template <class _Dummy>
476 __stl_debug_engine<_Dummy>::_Check_if_owner( const __owned_list * __l, const __owned_link& __it)
478 const __owned_list* __owner_ptr = __it._Owner();
479 _STLP_VERBOSE_RETURN(__owner_ptr!=0, _StlMsg_INVALID_ITERATOR)
480 _STLP_VERBOSE_RETURN(__l==__owner_ptr, _StlMsg_NOT_OWNER)
487 #endif /* _STLP_DEBUG */
489 #endif /* if defined (EXPOSE_GLOBALS_IMPLEMENTATION) */
491 #endif /* header guard */