
Here is the latest form using what I believe is the Meyer form of the singleton. What I was using earlier was from the GoF book on patterns. They use a pointer and instead of a static variable. I would appreciate any comments on this code. The intent is to provide a single-threaded tracing capability which is logged to a file. ----------- HEADER ----------------- #ifndef LIBREVERSE_TRACE_H #define LIBREVERSE_TRACE_H #include <boost/cstdint.hpp> #include <boost/shared_ptr.hpp> #include <fstream> #include "Reverse.h" namespace libreverse { namespace trace { /* Idea taken from http://www.codeproject.com/debug/xytrace.asp * (28 Jan 2002 - Xiangyang Liu) * * I have modified this so that we don't use varargs and use constant types */ class Trace_State { public: typedef boost::shared_ptr<Trace_State> ptr_t; static Trace_State& Instance(); void set_Trace_File_Prefix ( std::string name ); void set_Trace_Level ( boost::uint32_t level ); void open_Trace_File ( void ); std::string get_ID_String ( void ); void close_Trace_File ( void ); boost::uint32_t get_Trace_Level ( void ) const; void write_Message ( boost::uint32_t level, std::string msg ); private: Trace_State(); virtual ~Trace_State(); std::string m_file_prefix; boost::uint32_t m_trace_level; std::ofstream m_log_stream; }; class Trace { public: static bool write_Trace ( boost::uint32_t level, std::string message ); }; } /* namespace trace */ } /* namespace trace */ #endif /* LIBREVERSE_TRACE_H */ --------- SOURCE ------------- #include "Trace.h" #include <boost/format.hpp> #include <boost/date_time/posix_time/posix_time.hpp> #include <sstream> #ifndef WIN32 #include <unistd.h> #else #include <windows.h> #endif /* WIN32 */ namespace libreverse { namespace trace { Trace_State& Trace_State::Instance() { static Trace_State instance_obj; return instance_obj; } void Trace_State::set_Trace_File_Prefix ( std::string name ) { assert ( ! name.empty() ); // Lock the resource // Close the present file m_file_prefix = name; // Unlock the resource } void Trace_State::set_Trace_Level ( boost::uint32_t level ) { // Lock the resource // Change level m_trace_level = level; // Unlock the resource } void Trace_State::open_Trace_File ( void ) { if ( ! m_log_stream.is_open() ) { // Create file name std::stringstream name; name << boost::format("%s_%s.txt") % m_file_prefix % this->get_ID_String(); m_log_stream.open ( (name.str()).c_str() ); } } std::string Trace_State::get_ID_String ( void ) { // Create id string std::stringstream name; // Get current time boost::posix_time::ptime now = boost::posix_time::second_clock::local_time(); std::tm tm_ref = boost::posix_time::to_tm ( now ); boost::gregorian::date today = now.date(); name << boost::format ( "%s_%02d:%02d:%02d" ) % boost::gregorian::to_iso_extended_string ( today ) % tm_ref.tm_hour % tm_ref.tm_min % tm_ref.tm_sec; return name.str(); } void Trace_State::close_Trace_File ( void ) { if ( m_log_stream.is_open() ) { m_log_stream.close(); } } boost::uint32_t Trace_State::get_Trace_Level ( void ) const { boost::uint32_t level = 0; // Lock the resource // get the level level = m_trace_level; // unlock the resource // return the level return level; } void Trace_State::write_Message ( boost::uint32_t level, std::string msg ) { // Write ID m_log_stream << boost::format("%s_%d: " ) % this->get_ID_String() #ifndef WIN32 % getpid() #else % GetCurrentProcessId() #endif /* WIN32 */ << std::flush; // Write message prefix if ( level == libreverse::api::TraceLevel::TraceWarn ) { m_log_stream << "(WW) "; } else if ( level == libreverse::api::TraceLevel::TraceError ) { m_log_stream << "(EE) "; } else if ( level == libreverse::api::TraceLevel::TraceInfo ) { m_log_stream << "(II) "; } else if ( level == libreverse::api::TraceLevel::TraceDebug ) { m_log_stream << "(DEBUG) "; } else if ( level == libreverse::api::TraceLevel::TraceDetail ) { m_log_stream << "(DETAIL) "; } else if ( level == libreverse::api::TraceLevel::TraceData ) { m_log_stream << "(DATA) "; } else { // We should not be here abort(); } // Write to the file m_log_stream << msg << std::endl << std::flush; // Unlock the resource } Trace_State::Trace_State() : m_file_prefix ( "Trace" ), m_trace_level ( libreverse::api::TraceLevel::TraceNone ) {} Trace_State::~Trace_State() { this->close_Trace_File(); } #ifdef LIBREVERSE_DEBUG bool Trace::write_Trace ( boost::uint32_t level, std::string message ) { // If the level is equal to or greater than the present // level we record out message. if ( ( Trace_State::Instance().get_Trace_Level() != 0 ) && ( level <= Trace_State::Instance().get_Trace_Level() ) ) { Trace_State::Instance().write_Message ( level, message ); } return true; } #else bool Trace::write_Trace ( boost::uint32_t, std::string ) { return true; } #endif } /* namespace trace */ } /* namespace trace */