TuttleOFX  1
TuttleOFX/libraries/tuttle/src/tuttle/common/utils/backtrace.hpp
Go to the documentation of this file.
00001 //
00002 //  Copyright (c) 2010 Artyom Beilis (Tonkikh)
00003 //
00004 //  Distributed under the Boost Software License, Version 1.0. (See
00005 //  accompanying file LICENSE_1_0.txt or copy at
00006 //  http://www.boost.org/LICENSE_1_0.txt)
00007 //
00008 #ifndef BOOST_BACKTRACE_HPP
00009 #define BOOST_BACKTRACE_HPP
00010 
00011 #include <boost/config.hpp>
00012 #include <stdexcept>
00013 #include <typeinfo>
00014 #include <vector>
00015 #include <iosfwd>
00016 #include <string>
00017 
00018 namespace boost {
00019 
00020 namespace stack_trace {
00021         int trace(void **addresses,int size);
00022         void write_symbols(void *const *addresses,int size,std::ostream &);
00023         std::string get_symbol(void *address);
00024         std::string get_symbols(void * const *address,int size);
00025 } // stack_trace
00026 
00027 
00028 class backtrace
00029 {
00030 public:
00031         static size_t const default_stack_size = 32;
00032 
00033         backtrace(size_t frames_no = default_stack_size) 
00034         {
00035                 if(frames_no == 0)
00036                         return;
00037                 frames_.resize(frames_no,0);
00038                 int size = stack_trace::trace(&frames_.front(),frames_no);
00039                 frames_.resize(size);
00040         }
00041 
00042         virtual ~backtrace() throw()
00043         {
00044         }
00045 
00046         size_t stack_size() const
00047         {
00048                 return frames_.size();
00049         }
00050 
00051         void *return_address(unsigned frame_no) const
00052         {
00053                 if(frame_no < stack_size())
00054                         return frames_[frame_no];
00055                 return 0;
00056         }
00057 
00058         void trace_line(unsigned frame_no,std::ostream &out) const
00059         {
00060                 if(frame_no < frames_.size())
00061                         stack_trace::write_symbols(&frames_[frame_no],1,out);
00062         }
00063 
00064         std::string trace_line(unsigned frame_no) const
00065         {
00066                 if(frame_no < frames_.size())
00067                         return stack_trace::get_symbol(frames_[frame_no]);
00068                 return std::string();
00069         }
00070 
00071         std::string trace() const
00072         {
00073                 if(frames_.empty())
00074                         return std::string();
00075                 return stack_trace::get_symbols(&frames_.front(),frames_.size());
00076         }
00077 
00078         void trace(std::ostream &out) const
00079         {
00080                 if(frames_.empty())
00081                         return;
00082                 stack_trace::write_symbols(&frames_.front(),frames_.size(),out);
00083         }
00084 
00085 private:
00086         std::vector<void *> frames_;
00087 };
00088 
00089 
00090 namespace details {
00091         class trace_manip {
00092         public:
00093                 trace_manip(backtrace const *tr) :
00094                         tr_(tr)
00095                 {
00096                 }
00097                 std::ostream &write(std::ostream &out) const
00098                 {
00099                         if(tr_)
00100                                 tr_->trace(out);
00101                         return out;
00102                 }
00103         private:
00104                 backtrace const *tr_;
00105         };
00106 
00107         inline std::ostream &operator<<(std::ostream &out,details::trace_manip const &t)
00108         {
00109                 return t.write(out);
00110         }
00111 }
00112 
00113 template<typename E>
00114 details::trace_manip trace(E const &e)
00115 {
00116         backtrace const *tr = dynamic_cast<backtrace const *>(&e);
00117         return details::trace_manip(tr);
00118 }
00119 
00120 
00121 } // boost
00122 
00123 #endif
00124 // vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4
00125