I am trying to create a class for performing log tracing. While my
present program is single threaded as far as my code is concerned this
may not always be the case. Below is the code that I am proposing to
use. What I am weak on is concurrent programming. I know that I need to
use a mutex but I am not sure how to use the boost thread mutex library
and locks. Can someone comment on how I can modify the Trace_State class
to use locking?
Stephen
----------------
#include
#include
#include <fstream>
#include
#include <sstream>
#include
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 TraceLevel {
public:
static boost::uint32_t TraceNone; // No trace
static boost::uint32_t TraceError; // Only trace error
static boost::uint32_t TraceInfo; // Some extra information
static boost::uint32_t TraceDebug; // Debugging information
static boost::uint32_t TraceDetail; // Detailed debugging
information
};
boost::uint32_t TraceLevel::TraceNone = 0;
boost::uint32_t TraceLevel::TraceError = 10;
boost::uint32_t TraceLevel::TraceInfo = 20;
boost::uint32_t TraceLevel::TraceDebug = 30;
boost::uint32_t TraceLevel::TraceDetail = 40;
class Trace_State {
public:
typedef boost::shared_ptr ptr_t;
static Trace_State::ptr_t Instance()
{
// Lock the resource?
if ( m_instance.get() == 0 )
{
m_instance = Trace_State::ptr_t ( new
Trace_State() );
}
// Unlock the resource?
return m_instance;
}
void 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 set_Trace_Level ( boost::uint32_t level )
{
// Lock the resource
// Change level
m_trace_level = level;
// Unlock the resource
}
void open_Trace_File ( void )
{
// Create file name
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_%s_%02d:%02d:%02d.txt" )
% m_file_prefix
% boost::gregorian::to_iso_extended_string ( today )
% tm_ref.tm_hour
% tm_ref.tm_min
% tm_ref.tm_sec;
m_log_stream.open ( (name.str()).c_str() );
}
void close_Trace_File ( void )
{
m_log_stream.close();
}
boost::uint32_t 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 write_Message ( std::string msg )
{
// Lock the resource
// Write to the file
m_log_stream << msg;
// Unlock the resource
}
private:
Trace_State()
: m_file_prefix ( "Trace" ),
m_trace_level ( TraceLevel::TraceNone )
{}
static Trace_State::ptr_t m_instance;
std::string m_file_prefix;
boost::uint32_t m_trace_level;
//boost::recursive_mutex m_mutex;
std::ofstream m_log_stream;
};
Trace_State::ptr_t Trace_State::m_instance;
class Trace {
public:
static void write_Trace ( boost::uint32_t level,
std::string message )
{
Trace_State::ptr_t state_ptr = Trace_State::Instance();
// If the level is equal to or greater than the present
// level we record out message.
if ( level >= state_ptr->get_Trace_Level() )
{
state_ptr->write_Message ( message );
}
}
};
} /* namespace trace */
} /* namespace trace */
int main (int, char**)
{
libreverse::trace::Trace_State::ptr_t state_ptr =
libreverse::trace::Trace_State::Instance();
state_ptr->set_Trace_File_Prefix ("Funky");
state_ptr->open_Trace_File();
state_ptr->close_Trace_File();
return 0;
}