C ++ std :: list as static member variable & mdash; competition problems?

advertisements

I wrote a class in charge of keeping track of error messages, which uses a static std::list to keep track of the messages. I subclass most other classes from this, to give them the ability to write to a common error log. At program close the error log is written to a file. This is a multithreaded application however ... it occurred to me I might be asking for problems here ...

class ErrorLogger
{
public:
  void writeErrorMessage( string message );
  // ... etc
private:
  std::list<string> _theErrorMessages;
  // ... etc
};

I've been deriving several classes from this. Superficial example:

class MultiThreadingWidget : public ErrorLogger
{
public:
  void run()
  {
     // ...
     if( !isWorking )
     { writeErrorMessage( "MultiThreadingWidget::run failed()..."); };
     // ...
  }
};

To be frank, I'm not terribly concerned about concurrency issues as they affect the error log -- during the multithreaded part of the run, if there's an error worthy of being written to the log, it's almost certainly a fatal error -- but I am concerned about performance issues.

Would it be better making the ErrorLog a Singleton pattern, or is that for all practical purposes the same thing?

Exceptions are not an option for this project.

Thanks in advance!


I wrote a class in charge of keeping track of error messages, which uses a static std::list to keep track of the messages.

it's not declared as static -- which is it?

EDIT: saw that was a typo, and that it should have been declared static. however, the suggestion at the end of the response may help you attain the best speed without introducing threading errors.

To be frank, I'm not terribly concerned about concurrency issues as they affect the error log -- during the multithreaded part of the run, if there's an error worthy of being written to the log, it's almost certainly a fatal error -- but I am concerned about performance issues.

your concerns are backwards -- there's no reason to introduce a bug which is difficult to track and can be easily avoided.

Q: if it's almost certainly fatal and thus (hopefully) quite rare, what will a lock cost during regular execution?

A: only some memory (for the lock). you will not write to it often.

Q: why would that cost be significant at this stage in execution?

A: the program has probably encountered something fatal

Q: why is a properly written parallel program considered to be too slow, or even slower than a single threaded implementation on typical hardware?

A: they're not. just write your program for current and future machines. ok, there are some cases where this is not good, but i suspect that is not the case since you're writing other parts of the program for concurrent execution.

you should write your implementation for concurrency, if performance really is important here.

Would it be better making the ErrorLog a Singleton pattern, or is that for all practical purposes the same thing?

no. create multiple instances which hold their own messages, if that's how you prefer to classify messages. multiple instances will reduce contest for the logger types if: 1) speed is important 2) you really have a lot of messages to log

using multiple loggers, your caller won't wait to acquire a lock as often, if you have a lot of messages to write and the messages are pushed from multiple threads.

at termination, gather all the messages from all loggers and write them to disk. this way the different loggers (with different contexts) can output their messages by category (instance), or time (if you prefer).

if you know it's fatal, then reconsider an immediate write (as 0xC0DEFACE suggests).