Question

I'm writing a singleton Logger class in c++. this class provides logging API to multiple threads. to make it thread safe I'm using wxCRIT_SECT_LOCKER macro.

say I have this in my Logger class the following functions (simple example):

void Logger::error( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

  // do something such as getting/setting class members 
  m_err_cnt++;

  do_log("Error: " + msg);
}

void Logger::warning( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

  // do something such as getting/setting class members 
  m_warn_cnt++;

  do_log("Warning: " + msg);
}

void Logger::do_log( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);

  // do something such as getting/setting class members 
  m_log_cnt++;


  cout << msg << endl;
}

Problem:

when Logger::warning() is called we'll enter the critical section twice, once in Logger::warning() and one more time in *Logger::do_log()*.

If you agree the problem is real and can cause deadlock, how can I avoid multiple locks (using wxCriticalSection class/macros).

Était-ce utile?

La solution

What is often done is to create internal APIs that do not take locks that are called by the public APIs that do take the locks.

void Logger::error( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
  m_err_cnt++;
  do_log_internal("Error: " + msg);
}

void Logger::warning( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
  m_warn_cnt++;
  do_log_internal("Warning: " + msg);
}

void Logger::do_log( string msg )
{
  wxCRIT_SECT_LOCKER(adapter_locker, gs_LogBufferShield);
  do_log_internal(msg);
}

void Logger::do_log_internal( string msg )
{
  m_log_cnt++;
  cout << msg << endl;
}

However, for your problem, you may rather use wxMutex directly, and use the type wxMUTEX_RECURSIVE when you construct it. This way, a mutex has count. When the mutex is first locked, the count is set to 1. If the same thread grabs the mutex again, it increments a count. Releasing the mutex decrements the count. When the count reaches 0, the mutex is unlocked.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top