ML Reference
|
00001 // **InsertLicense** code 00002 //---------------------------------------------------------------------------------- 00010 00016 //---------------------------------------------------------------------------------- 00017 00018 #ifndef __mlTrace_H 00019 #define __mlTrace_H 00020 00021 #ifndef __mlUtilsSystem_H 00022 #include "mlUtilsSystem.h" 00023 #endif 00024 00025 00026 ML_UTILS_START_NAMESPACE 00027 00028 //------------------------------------------------------------------------- 00050 //------------------------------------------------------------------------- 00051 template <typename INDEXTYPE> class TraceBuffer { 00052 public: 00053 //----------------------------------------------------------- 00056 //----------------------------------------------------------- 00057 inline TraceBuffer() 00058 { 00059 // Initialize both buffers with NULL pointers. 00060 memset(_traceStack, 0, _numBufBytes); 00061 memset(_traceList, 0, _numBufBytes); 00062 00063 // Reset indices into stack and list. 00064 _traceStackTop = 0; 00065 _traceListEnd = 0; 00066 } 00067 00068 //----------------------------------------------------------- 00075 //----------------------------------------------------------- 00076 inline void add(const char* const traceInString){ 00077 // Push string address onto the stack. Be sure that 00078 // _stackTop is incremented after storing pointer to 00079 // make memory access and incrementation of index independent. 00080 // So the CPU can execute both statements in parallel. 00081 // Also be sure to increment index NOT within "[" and "]" 00082 // to avoid that indexing works on 32bit integers which would 00083 // access areas outside buffers 00084 _traceStack[_traceStackTop] = traceInString; 00085 00086 // Do not increment inside [ and ] because that could be evaluated 00087 // to an integer which would lead to illegal out of range accesses. 00088 ++_traceStackTop; 00089 00090 // Append string address to end of trace list. For optimizing 00091 // performance also see _traceStack push above. 00092 _traceList[_traceListEnd] = traceInString; 00093 00094 // Do not increment inside [ and ] because that could be evaluated 00095 // to an integer which would lead to illegal out of range accesses. 00096 ++_traceListEnd; 00097 } 00098 00099 //----------------------------------------------------------- 00103 //----------------------------------------------------------- 00104 inline void remove(){ 00105 // Decrement trace stack top. Be sure that integer index 00106 // is really limited to size of INDEXTYPE since passing 00107 // decremented _traceStackTop without masking it could 00108 // lead to usage of 32 bit index in index "[" "]" and 00109 // accesses outside buffers. Note that mask calculation 00110 // is constant and probably will be evaluated on compile 00111 // time. 00112 _traceStackTop = static_cast<INDEXTYPE>((_traceStackTop - 1) & _bufferIndexMask); 00113 00114 // Reset stack entry. So unused entries do not use 00115 // invalid information. 00116 _traceStack[_traceStackTop] = NULL; 00117 } 00118 00119 //----------------------------------------------------------- 00122 //----------------------------------------------------------- 00123 inline INDEXTYPE getTraceStackTop() const { return _traceStackTop; } 00124 00125 //----------------------------------------------------------- 00128 //----------------------------------------------------------- 00129 inline INDEXTYPE getTraceListEnd() const { return _traceListEnd; } 00130 00131 //----------------------------------------------------------- 00133 //----------------------------------------------------------- 00134 inline const char* const *getTraceStack() const { return _traceStack; } 00135 00136 //----------------------------------------------------------- 00138 //----------------------------------------------------------- 00139 inline const char* const *getTraceList() const { return _traceList; } 00140 00141 private: 00142 00147 enum { _numBufEntries = (1L << (sizeof(INDEXTYPE) << 3)) , 00148 _numBufBytes = _numBufEntries * sizeof(const char *), 00149 _bufferIndexMask = _numBufEntries - 1 00150 }; 00151 00153 INDEXTYPE _traceStackTop; 00154 00156 INDEXTYPE _traceListEnd; 00157 00159 const char *_traceStack[_numBufEntries]; 00160 00162 const char *_traceList[_numBufEntries]; 00163 }; 00164 00165 //------------------------------------------------------------------------- 00178 //------------------------------------------------------------------------- 00179 template <typename INDEXTYPE> class Trace { 00180 public: 00181 00182 //----------------------------------------------------------- 00193 //----------------------------------------------------------- 00194 inline Trace(const char * const traceInString, TraceBuffer<INDEXTYPE> &traceBuf) : 00195 _traceBuf(traceBuf) 00196 { 00197 // Push string address on stack and at end of trace list. 00198 traceBuf.add(traceInString); 00199 } 00200 00201 //----------------------------------------------------------- 00208 //----------------------------------------------------------- 00209 inline ~Trace() 00210 { 00211 _traceBuf.remove(); 00212 } 00213 00214 private: 00215 00219 TraceBuffer<INDEXTYPE> &_traceBuf; 00220 00221 00224 inline Trace(const Trace &trace) : _traceBuf(trace._traceBuf){ } 00225 00229 inline Trace<INDEXTYPE> &operator=(const Trace & /* trace */){ return *this; } 00230 }; 00231 00232 00233 //--------------------------------------------------------------------------- 00235 //--------------------------------------------------------------------------- 00236 typedef MLuint16 MLGlobalTraceBufferType; 00237 00238 //--------------------------------------------------------------------------- 00242 //--------------------------------------------------------------------------- 00243 extern ML_UTILS_EXPORT TraceBuffer<MLGlobalTraceBufferType> MLGlobalTraceBuffer; 00244 00245 00246 ML_UTILS_END_NAMESPACE 00247 00248 00249 #endif // __mlTrace_H 00250