Open Inventor Reference
MeVis/ThirdParty/Sources/Inventor/inventor/lib/mevis/include/Inventor/SoTrace.h
Go to the documentation of this file.
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_