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 <Inventor/SbTypeDefs.h>
00055 
00065 
00066 #if !defined(DISABLE_ERRORTRACING)
00067 
00068 # define SO_TRACE_IN(__classAndMethod___)  \
00069    static const char *const __SO_TRACE_IN_STRING_BUF = __FILE__ ":" __classAndMethod___; \
00070    SoTrace<uint16_t> __SoTraceObject(__SO_TRACE_IN_STRING_BUF, SoGlobalTraceBuffer);
00071 
00072 #else
00073 
00074 # define SO_TRACE_IN(__classAndMethod___)
00075 
00076 #endif  // DISABLE_ERRORTRACING
00077 
00079 typedef uint16_t SoGlobalTraceBufferType;
00080 
00081 
00082 
00101 
00102 template <typename INDEXTYPE> class SoTraceBuffer
00103 {
00104    public:
00105 
00108       inline SoTraceBuffer() {
00109          _initClass();
00110       }
00111 
00118       inline void       add(const char *const traceInString) {
00126          _traceStack[_traceStackTop] = traceInString;
00127          ++_traceStackTop;
00128 
00131          _traceList[_traceListEnd] = traceInString;
00132          ++_traceListEnd;
00133       }
00134 
00138       inline void       remove() {
00146          _traceStackTop = static_cast<INDEXTYPE>((_traceStackTop - 1) & _bufferIndexMask);
00147 
00150          _traceStack[_traceStackTop] = NULL;
00151       }
00152 
00155       inline INDEXTYPE  getTraceStackTop() const {
00156          return _traceStackTop;
00157       }
00158 
00161       inline INDEXTYPE  getTraceListEnd() const {
00162          return _traceListEnd;
00163       }
00164 
00166       inline const char *const *getTraceStack() const {
00167          return _traceStack;
00168       }
00169 
00171       inline const char *const *getTraceList() const {
00172          return _traceList;
00173       }
00174 
00176       inline SoGlobalTraceBufferType getMaxNumTraceListDumps() const {
00177          return _maxNumTraceListDumps;
00178       }
00179 
00181       inline void       setMaxNumTraceListDumps(SoGlobalTraceBufferType num) {
00182          _maxNumTraceListDumps = num;
00183       }
00184 
00186       inline SoGlobalTraceBufferType getMaxNumTraceStackDumps() const {
00187          return _maxNumTraceStackDumps;
00188       }
00189 
00191       inline void       setMaxNumTraceStackDumps(SoGlobalTraceBufferType num) {
00192          _maxNumTraceStackDumps = num;
00193       }
00194 
00197       SbString          getTraceDumpString() const;
00198 
00199    private:
00200 
00203       inline void       _initClass() {
00205          memset(_traceStack, 0, _numBufBytes);
00206          memset(_traceList,  0, _numBufBytes);
00207 
00209          _traceStackTop = 0;
00210          _traceListEnd  = 0;
00211       }
00212 
00217       enum {
00218          _numBufEntries   = (1L << (sizeof(INDEXTYPE) << 3)) ,
00219          _numBufBytes     = _numBufEntries * sizeof(const char *),
00220          _bufferIndexMask = _numBufEntries - 1
00221       };
00222 
00224       INDEXTYPE         _traceStackTop;
00225 
00227       INDEXTYPE         _traceListEnd;
00228 
00230       const char       *_traceStack[_numBufEntries];
00231 
00233       const char       *_traceList[_numBufEntries];
00234 
00237       SoGlobalTraceBufferType _maxNumTraceListDumps;
00238 
00241       SoGlobalTraceBufferType _maxNumTraceStackDumps;
00242 };
00243 
00244 
00253 
00254 extern INVENTOR_API SoTraceBuffer<SoGlobalTraceBufferType> SoGlobalTraceBuffer;
00255 
00256 
00257 template <typename INDEXTYPE>
00258 SbString
00259 SoTraceBuffer<INDEXTYPE>::getTraceDumpString() const
00260 {
00261   try {
00263     char num[512] = "";
00264 
00265     SbString endLineStr = "\n";
00266 
00269     SbString                traceListStr = "";
00270     SoGlobalTraceBufferType indexCounter = 0;
00271     SoGlobalTraceBufferType entry        = 0;
00272 
00273     if((_maxNumTraceStackDumps > 0) && (getTraceStackTop() > 0)) {
00274       sprintf(num, "\nCall stack of the last %d traced functions:\n", _maxNumTraceStackDumps);
00275       traceListStr += num;
00276 
00278       SoGlobalTraceBufferType stackCnt    = 0;
00279       const char * const *traceStack      = getTraceStack();
00280       SoGlobalTraceBufferType stackTop    = getTraceStackTop();
00281       SoGlobalTraceBufferType stackPreTop = stackTop;
00282       stackPreTop--;
00283       indexCounter = 1;
00284 
00285       for(entry = stackPreTop; (entry != stackTop) && (stackCnt < _maxNumTraceStackDumps); entry--, stackCnt++) {
00287         sprintf(num, "%5d ", indexCounter);
00288 
00290         const char *entryStrPtr = traceStack[entry];
00291 
00292         if(entryStrPtr) {
00293           traceListStr += ((SbString)num);
00294           traceListStr += entryStrPtr;
00295           traceListStr += endLineStr;
00296         }
00297 
00299         indexCounter++;
00300       }
00301     }
00302 
00303     if(_maxNumTraceListDumps > 0) {
00304       SoGlobalTraceBufferType listCnt = 0;
00305       sprintf(num, "\nCall list of the %d most recently traced functions:\n", _maxNumTraceListDumps);
00306       traceListStr += num;
00307       SoGlobalTraceBufferType listEnd    = getTraceListEnd();
00308       SoGlobalTraceBufferType listPreEnd = listEnd;
00309       listPreEnd--;
00310       indexCounter = 1;
00311       const char * const *traceList = SoGlobalTraceBuffer.getTraceList();
00312       entry=0;
00313 
00314       for(entry = listPreEnd; (entry != listEnd) && (listCnt < _maxNumTraceListDumps); entry--, listCnt++) {
00316         sprintf(num, "%5d ", indexCounter);
00317 
00319         const char *entryStrPtr = traceList[entry];
00320 
00321         if(entryStrPtr) {
00322           traceListStr += ((SbString)num);
00323           traceListStr += entryStrPtr;
00324           traceListStr += endLineStr;
00325         }
00326 
00328         indexCounter++;
00329       }
00330     }
00331 
00333     return traceListStr;
00334   }
00335   catch(...) {
00336     return "<Could not determine last called functions or function stack>";
00337   }
00338 }
00339 
00340 
00355 
00356 template <typename INDEXTYPE> class SoTrace
00357 {
00358    public:
00359 
00370       inline SoTrace(const char *const traceInString, SoTraceBuffer<INDEXTYPE> &traceBuf) : _traceBuf(traceBuf) {
00372          traceBuf.add(traceInString);
00373       }
00374 
00381       inline ~SoTrace() {
00382          _traceBuf.remove();
00383       }
00384 
00385    private:
00386 
00390       SoTraceBuffer<INDEXTYPE> &_traceBuf;
00391 
00394       inline SoTrace(const SoTrace &trace) : _traceBuf(trace._traceBuf) {
00395       }
00396 
00400       inline SoTrace<INDEXTYPE> &operator=(const SoTrace &trace) {
00401          return *this;
00402       }
00403 };
00404 
00405 #endif  // _SO_TYPE_