Open Inventor Reference
|
00001 /* 00002 * 00003 * Copyright (C) 2004 MeVis gGmbH All Rights Reserved. 00004 * 00005 * This library is free software; you can redistribute it and/or 00006 * modify it under the terms of the GNU Lesser General Public 00007 * License as published by the Free Software Foundation; either 00008 * version 2.1 of the License, or (at your option) any later version. 00009 * 00010 * This library is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00013 * Lesser General Public License for more details. 00014 * 00015 * Further, this software is distributed without any warranty that it is 00016 * free of the rightful claim of any third person regarding infringement 00017 * or the like. Any license provided herein, whether implied or 00018 * otherwise, applies only to this software file. Patent licenses, if 00019 * any, provided herein do not apply to combinations of this program with 00020 * other software, or any other product whatsoever. 00021 * 00022 * You should have received a copy of the GNU Lesser General Public 00023 * License along with this library; if not, write to the Free Software 00024 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00025 * 00026 * Contact information: MeVis, Center for Medical Diagnostic Systems and 00027 * Visualization GmbH, Universit�tsallee 29, D-28359 Bremen, GERMANY, or: 00028 * 00029 * http://www.mevis.de 00030 * 00031 */ 00032 00033 /* 00034 * Copyright (C) 2004 MeVis Research GmbH 00035 * 00036 _______________________________________________________________________ 00037 _______________ M E V I S R E S E A R C H G M B H _______________ 00038 | 00039 | Description: 00040 | This include file contains a class to manage a buffer for a stack 00041 | and a list of string pointers for tracing debug and release code. 00042 | 00043 | Author(s) : Wolf Spindler, Felix Ritter 00044 | 00045 _______________ M E V I S R E S E A R C H G M B H _______________ 00046 _______________________________________________________________________ 00047 */ 00048 00049 #ifndef _SO_TRACE_ 00050 #define _SO_TRACE_ 00051 00052 #include <Inventor/system/SbSystem.h> 00053 #include <Inventor/SbString.h> 00054 #include <inttypes.h> 00055 #include <stdint.h> 00056 00057 00067 00068 #if !defined(DISABLE_ERRORTRACING) 00069 00070 # define SO_TRACE_IN(__classAndMethod___) \ 00071 static const char *const __SO_TRACE_IN_STRING_BUF = __FILE__ ":" __classAndMethod___; \ 00072 SoTrace<uint16_t> __SoTraceObject(__SO_TRACE_IN_STRING_BUF, SoGlobalTraceBuffer); 00073 00074 #else 00075 00076 # define SO_TRACE_IN(__classAndMethod___) 00077 00078 #endif // DISABLE_ERRORTRACING 00079 00081 typedef uint16_t SoGlobalTraceBufferType; 00082 00083 00084 00103 00104 template <typename INDEXTYPE> class SoTraceBuffer 00105 { 00106 public: 00107 00110 inline SoTraceBuffer() { 00111 _initClass(); 00112 } 00113 00120 inline void add(const char *const traceInString) { 00128 _traceStack[_traceStackTop] = traceInString; 00129 ++_traceStackTop; 00130 00133 _traceList[_traceListEnd] = traceInString; 00134 ++_traceListEnd; 00135 } 00136 00140 inline void remove() { 00148 _traceStackTop = (INDEXTYPE)((_traceStackTop - 1) & _bufferIndexMask); 00149 00152 _traceStack[_traceStackTop] = NULL; 00153 } 00154 00157 inline INDEXTYPE getTraceStackTop() const { 00158 return _traceStackTop; 00159 } 00160 00163 inline INDEXTYPE getTraceListEnd() const { 00164 return _traceListEnd; 00165 } 00166 00168 inline const char *const *getTraceStack() const { 00169 return _traceStack; 00170 } 00171 00173 inline const char *const *getTraceList() const { 00174 return _traceList; 00175 } 00176 00178 inline SoGlobalTraceBufferType getMaxNumTraceListDumps() const { 00179 return _maxNumTraceListDumps; 00180 } 00181 00183 inline void setMaxNumTraceListDumps(SoGlobalTraceBufferType num) { 00184 _maxNumTraceListDumps = num; 00185 } 00186 00188 inline SoGlobalTraceBufferType getMaxNumTraceStackDumps() const { 00189 return _maxNumTraceStackDumps; 00190 } 00191 00193 inline void setMaxNumTraceStackDumps(SoGlobalTraceBufferType num) { 00194 _maxNumTraceStackDumps = num; 00195 } 00196 00199 SbString getTraceDumpString() const; 00200 00201 private: 00202 00205 inline void _initClass() { 00207 memset(_traceStack, 0, _numBufBytes); 00208 memset(_traceList, 0, _numBufBytes); 00209 00211 _traceStackTop = 0; 00212 _traceListEnd = 0; 00213 } 00214 00219 enum { 00220 _numBufEntries = (1L << (sizeof(INDEXTYPE) << 3)) , 00221 _numBufBytes = _numBufEntries * sizeof(const char *), 00222 _bufferIndexMask = _numBufEntries - 1 00223 }; 00224 00226 INDEXTYPE _traceStackTop; 00227 00229 INDEXTYPE _traceListEnd; 00230 00232 const char *_traceStack[_numBufEntries]; 00233 00235 const char *_traceList[_numBufEntries]; 00236 00239 SoGlobalTraceBufferType _maxNumTraceListDumps; 00240 00243 SoGlobalTraceBufferType _maxNumTraceStackDumps; 00244 }; 00245 00246 00255 00256 extern INVENTOR_API SoTraceBuffer<SoGlobalTraceBufferType> SoGlobalTraceBuffer; 00257 00258 00259 template <typename INDEXTYPE> 00260 SbString 00261 SoTraceBuffer<INDEXTYPE>::getTraceDumpString() const 00262 { 00263 try { 00265 char num[512] = ""; 00266 00267 SbString endLineStr = "\n"; 00268 00271 SbString traceListStr = ""; 00272 SoGlobalTraceBufferType indexCounter = 0; 00273 SoGlobalTraceBufferType entry = 0; 00274 00275 if((_maxNumTraceStackDumps > 0) && (getTraceStackTop() > 0)) { 00276 sprintf(num, "\nCall stack of the last %d traced functions:\n", _maxNumTraceStackDumps); 00277 traceListStr += num; 00278 00280 SoGlobalTraceBufferType stackCnt = 0; 00281 const char * const *traceStack = getTraceStack(); 00282 SoGlobalTraceBufferType stackTop = getTraceStackTop(); 00283 SoGlobalTraceBufferType stackPreTop = stackTop; 00284 stackPreTop--; 00285 indexCounter = 1; 00286 00287 for(entry = stackPreTop; (entry != stackTop) && (stackCnt < _maxNumTraceStackDumps); entry--, stackCnt++) { 00289 sprintf(num, "%5d ", indexCounter); 00290 00292 const char *entryStrPtr = traceStack[entry]; 00293 00294 if(entryStrPtr) { 00295 traceListStr += ((SbString)num); 00296 traceListStr += entryStrPtr; 00297 traceListStr += endLineStr; 00298 } 00299 00301 indexCounter++; 00302 } 00303 } 00304 00305 if(_maxNumTraceListDumps > 0) { 00306 SoGlobalTraceBufferType listCnt = 0; 00307 sprintf(num, "\nCall list of the %d most recently traced functions:\n", _maxNumTraceListDumps); 00308 traceListStr += num; 00309 SoGlobalTraceBufferType listEnd = getTraceListEnd(); 00310 SoGlobalTraceBufferType listPreEnd = listEnd; 00311 listPreEnd--; 00312 indexCounter = 1; 00313 const char * const *traceList = SoGlobalTraceBuffer.getTraceList(); 00314 entry=0; 00315 00316 for(entry = listPreEnd; (entry != listEnd) && (listCnt < _maxNumTraceListDumps); entry--, listCnt++) { 00318 sprintf(num, "%5d ", indexCounter); 00319 00321 const char *entryStrPtr = traceList[entry]; 00322 00323 if(entryStrPtr) { 00324 traceListStr += ((SbString)num); 00325 traceListStr += entryStrPtr; 00326 traceListStr += endLineStr; 00327 } 00328 00330 indexCounter++; 00331 } 00332 } 00333 00335 return traceListStr; 00336 } 00337 catch(...) { 00338 return "<Could not determine last called functions or function stack>"; 00339 } 00340 } 00341 00342 00357 00358 template <typename INDEXTYPE> class SoTrace 00359 { 00360 public: 00361 00372 inline SoTrace(const char *const traceInString, SoTraceBuffer<INDEXTYPE> &traceBuf) : _traceBuf(traceBuf) { 00374 traceBuf.add(traceInString); 00375 } 00376 00383 inline ~SoTrace() { 00384 _traceBuf.remove(); 00385 } 00386 00387 private: 00388 00392 SoTraceBuffer<INDEXTYPE> &_traceBuf; 00393 00396 inline SoTrace(const SoTrace &trace) : _traceBuf(trace._traceBuf) { 00397 } 00398 00402 inline SoTrace<INDEXTYPE> &operator=(const SoTrace &trace) { 00403 return *this; 00404 } 00405 }; 00406 00407 #endif // _SO_TYPE_