CallStack.h
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef FIX_CALLSTACK_H
00023 #define FIX_CALLSTACK_H
00024
00025 #ifdef _MSC_VER
00026 #pragma warning( disable : 4297 4550 4551 4552 4786 )
00027 #endif
00028
00029 #include <iostream>
00030 #include <exception>
00031 #include <map>
00032 #include <stack>
00033 #include <string>
00034 #include "Mutex.h"
00035
00036 namespace FIX
00037 {
00039 class CallStack
00040 {
00041 public:
00043 struct Method
00044 {
00045 Method() {}
00046 Method(const std::string& n, const std::string& f, int l)
00047 : name(n), file(f), line(l) {}
00048
00049 std::string name;
00050 std::string file;
00051 int line;
00052
00053 Method& operator=( const Method& rhs )
00054 {
00055 name = rhs.name;
00056 file = rhs.file;
00057 line = rhs.line;
00058 return *this;
00059 }
00060
00061 friend bool operator==( const Method& lhs, const Method& rhs );
00062 friend std::ostream& operator<<( std::ostream&, const Method& );
00063 };
00064
00066 class Context : public std::stack<Method>
00067 {
00068 public:
00069 Context() : ignore(false) {}
00070 void caught( std::exception& );
00071 void caught();
00072
00073 std::string exception;
00074 bool ignore;
00075 };
00076
00078 class Ignore
00079 {
00080 public:
00081 Ignore()
00082 { s_count++;
00083 CallStack::ignore(true);
00084 }
00085 ~Ignore()
00086 { s_count--;
00087 if( s_count == 0 )
00088 CallStack::ignore(false);
00089 }
00090
00091 private:
00092 static int s_count;
00093 };
00094
00095 CallStack(const std::string& name, const std::string& file, int line);
00096 ~CallStack();
00097
00098 static void output();
00099 static void ignore( bool );
00100 static void caught( std::exception& e );
00101 static void caught();
00102 static void terminate();
00103
00104 private:
00105 static Context& getContext();
00106 static Context& getErrorContext();
00107
00108 static std::map<thread_id, Context> s_stack;
00109 static std::map<thread_id, Context> s_error;
00110 static Mutex s_mutex;
00111 };
00112
00113 inline std::ostream& operator<<
00114 ( std::ostream& ostream, const CallStack::Method& method )
00115 {
00116 return ostream
00117 << method.name.c_str()
00118 << "(" << method.file.c_str() << ":" << method.line << ")";
00119 }
00120
00121 inline bool operator==( const CallStack::Method& rhs, const CallStack::Method& lhs )
00122 {
00123 return lhs.name == rhs.name
00124 && lhs.file == rhs.file
00125 && lhs.line == rhs.line;
00126 }
00127 }
00128
00129 #ifdef ENABLE_CALLSTACK
00130 #define QF_STACK_PUSH(name) \
00131 CallStack cs_(#name, __FILE__, __LINE__); \
00132 try \
00133 {
00134 #define QF_STACK_POP \
00135 } \
00136 catch( std::exception& e ) \
00137 { \
00138 CallStack::caught(e); \
00139 throw; \
00140 } \
00141 catch( ... ) \
00142 { \
00143 CallStack::caught(); \
00144 throw; \
00145 }
00146
00147 #define QF_STACK_IGNORE_BEGIN \
00148 { CallStack::Ignore ignore_;
00149 #define QF_STACK_IGNORE_END \
00150 }
00151
00152 #define QF_STACK_TRY \
00153 try {
00154 #define QF_STACK_CATCH \
00155 } catch( ... ) { FIX::CallStack::output(); throw; }
00156 #else //ENABLE_CALLSTACK
00157 #define QF_STACK_PUSH(name)
00158 #define QF_STACK_POP
00159 #define QF_STACK_IGNORE_BEGIN
00160 #define QF_STACK_IGNORE_END
00161 #define QF_STACK_TRY
00162 #define QF_STACK_CATCH
00163 #endif //ENABLE_CALLSTACK
00164
00165 #endif