00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #ifdef _MSC_VER
00021 #include "stdafx.h"
00022 #else
00023 #include "config.h"
00024 #endif
00025 #include "CallStack.h"
00026
00027 #include <sstream>
00028 #include <typeinfo>
00029
00030 namespace FIX
00031 {
00032 std::map<unsigned, CallStack::Context> CallStack::s_stack;
00033 std::map<unsigned, CallStack::Context> CallStack::s_error;
00034 Mutex CallStack::s_mutex;
00035 int CallStack::Ignore::s_count = 0;
00036
00037 CallStack::CallStack(const std::string& name, const std::string& file, int line)
00038 {
00039 Locker locker(s_mutex);
00040
00041 #if TERMINATE_IN_STD
00042 std::set_terminate(FIX::CallStack::terminate);
00043 #else
00044 set_terminate(FIX::CallStack::terminate);
00045 #endif
00046
00047 Context& c = getContext();
00048 if( !c.ignore )
00049 {
00050 c.push(Method(name, file, line));
00051 getErrorContext() = c;
00052 }
00053 }
00054
00055 CallStack::~CallStack()
00056 {
00057 Locker locker(s_mutex);
00058 Context& c = getContext();
00059 if( !c.ignore )
00060 c.pop();
00061 }
00062
00063 void CallStack::output()
00064 {
00065 Locker locker(s_mutex);
00066 std::map<unsigned, CallStack::Context>::iterator i;
00067 for( i = s_error.begin(); i != s_error.end(); ++i )
00068 {
00069 Context& c = i->second;
00070 if(c.size())
00071 std::cerr << "thread(" << i->first << "):" << c.exception << std::endl;
00072 while(c.size())
00073 {
00074 std::cerr << " at " << c.top() << std::endl;
00075 c.pop();
00076 }
00077 }
00078 }
00079
00080 void CallStack::ignore(bool value)
00081 {
00082 Locker locker(s_mutex);
00083 getContext().ignore = value;
00084 }
00085
00086 void CallStack::caught( std::exception& e )
00087 {
00088 Locker locker(s_mutex);
00089 Context& c = getErrorContext();
00090 if( c.ignore ) return;
00091 c.caught(e);
00092 }
00093
00094 void CallStack::caught()
00095 {
00096 Locker locker(s_mutex);
00097 Context& c = getErrorContext();
00098 if( c.ignore ) return;
00099 c.caught();
00100 }
00101
00102 CallStack::Context& CallStack::getContext()
00103 {
00104 Locker locker(s_mutex);
00105 return s_stack[thread_self()];
00106 }
00107
00108 CallStack::Context& CallStack::getErrorContext()
00109 {
00110 Locker locker(s_mutex);
00111 return s_error[thread_self()];
00112 }
00113
00114 void CallStack::terminate()
00115 {
00116 Locker locker(s_mutex);
00117 CallStack::output();
00118 abort();
00119 }
00120
00121 void CallStack::Context::caught( std::exception& e )
00122 {
00123 #if TYPEINFO_IN_STD
00124 const std::type_info&
00125 #else
00126 const type_info&
00127 #endif
00128 type = typeid(e);
00129
00130 std::stringstream s;
00131 s << type.name() << ": " << std::string(e.what());
00132 exception = s.str();
00133 }
00134
00135 void CallStack::Context::caught()
00136 {
00137 exception = "unknown exception";
00138 }
00139 }