Skip to content
Snippets Groups Projects
Commit df972b95 authored by Steven Murray's avatar Steven Murray
Browse files

After discussion with Giuseppe I have added two improvements that he has

kindly suggested.

Firstly the instance() method assumes that destroyInstance() is not called
concurrently with it so it can assume that in a multi-threaded scenario there is
a single transition from s_instance being NULL to s_instance pointing to a newly
created Log object.  This means the following mutex-less if statement can be at
the beginning of the instance() method to increase performance:

  if(NULL != s_instance) {
    return *s_instance;
  }

Secondly the destructor of the Log class should be private in order to prevent
clients from being able to directly delete the Log singleton.
parent e6ea621c
No related branches found
No related tags found
No related merge requests found
......@@ -55,6 +55,13 @@ castor::log::Log &castor::log::Log::instance(const std::string &programName)
throw(castor::exception::Internal, castor::exception::InvalidArgument) {
checkProgramNameLen(programName);
// The following "if NULL != s_instance" if statement assumes that the
// instance() method is not called concurrently with the destroyInstance()
// method
if(NULL != s_instance) {
return *s_instance;
}
{
const int rc = pthread_mutex_lock(&s_instanceMutex);
if(0 != rc) {
......@@ -168,6 +175,12 @@ castor::log::Log::Log(const std::string &programName)
initMutex();
}
//------------------------------------------------------------------------------
// destructor
//------------------------------------------------------------------------------
castor::log::Log::~Log() throw() {
}
//------------------------------------------------------------------------------
// determineMaxMsgLen
//------------------------------------------------------------------------------
......
......@@ -60,6 +60,10 @@ public:
* method once in the main thread of the program, because the instance()
* method uses a mutex to protect the creation of the Log singleton.
*
* Please note that it is thread safe to call the instance() method
* concurrently with itself, however it is NOT thread safe to call the
* instance() method concurrently with the destroyInstance() method.
*
* @param programName The name of the program to be prepended to every log
* message. The name should not be longer than
* castor::log::LOG_MAX_PROGNAMELEN characters.
......@@ -74,11 +78,16 @@ public:
* WARNING
* If you are not sure whether you should be using this method then please
* do not use it. You must be sure that no thread will try to use the
* Log singleton that was destoyed by a call to destroyInstance(). This
* method is intended to be used at cleanup time just before an executable
* exits. Calling this method just before an executable exits will free heap
* memory owned by the CASTOR logging system and therefore a memory profiler
* should not detect a memory leak related to the logging system.
* Log singleton that was destoyed by a call to destroyInstance(). You must
* also make sure that this method is not called concurrently with
* the instance() method because due to an optimisation in the instance()
* method, calling these two methods concurrently is NOT thread safe.
*
* This method is intended to be used at cleanup time just before an
* executable exits. Calling this method just before an executable exits
* will free heap memory owned by the CASTOR logging system and therefore a
* memory profiler should not detect a memory leak related to the logging
* system.
*/
static void destroyInstance() throw(castor::exception::Internal);
......@@ -245,6 +254,12 @@ private:
*/
Log(const std::string &programName) throw(castor::exception::Internal);
/**
* Private destructor to prevent clients from destroying the Log singleton
* themselves.
*/
~Log() throw();
/**
* Determines the maximum message length that the client syslog server can
* handle.
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment