![]() |
00001 /**************************************************************************** 00002 ** Copyright (c) quickfixengine.org All rights reserved. 00003 ** 00004 ** This file is part of the QuickFIX FIX Engine 00005 ** 00006 ** This file may be distributed under the terms of the quickfixengine.org 00007 ** license as defined by quickfixengine.org and appearing in the file 00008 ** LICENSE included in the packaging of this file. 00009 ** 00010 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE 00011 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 00012 ** 00013 ** See http://www.quickfixengine.org/LICENSE for licensing information. 00014 ** 00015 ** Contact ask@quickfixengine.org if any conditions of this licensing are 00016 ** not clear to you. 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<thread_id, CallStack::Context> CallStack::s_stack; 00033 std::map<thread_id, 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<thread_id, 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 }