Archive for March, 2007

KBattleShip update

March 31, 2007

KBattleShip development is going on quite well. Johann did an amazing job designing the ships, and we also have to thank Robert Wadley for the ‘hits’ and ‘misses’. Here’s a screenshot:

KBS4 screenshot

Rewriting KBattleShip

March 24, 2007

This week I’ve started a complete rewrite of KBattleShip. I’m using KGameCanvas on an MVC architecture and it’s coming along quite well. Here’s a screenshot:
KBS4 Screenshot
the ships are all scaled copies of the same one, because I’m waiting for Johann to finish the graphics :)

A smart logger

March 11, 2007

At work I’ve been asked to design a C++ logger class to be used like this:

Logger logger;
logger << "The universe will collapse in " << remaining_time << " seconds";

This seams like a very easy task, but has some hidden difficulties:

  1. A header should be automatically added when logging (with a timestamp, for example), but only at the first occurence of the insertion operator.
  2. There’s no termination character or manipulator to inform the logger object that a line is complete.
  3. The whole thing should be thread-safe at statement level, that is, you don’t want multiple concurrent logging statements to overlap in the logfile.

At first I thought that it was impossible to achieve all of this without altering the API, but after a bit of experimentation with the lifetime of temporary objects and the ownership transfer semantics of auto_ptr, I’ve come out with a solution based on a technique similar to template expressions.

The solution revolves around a template helper object like the following:

template <typename Helper, typename T>
class LoggerHelper { /* ... */ };

which is returned by value in each call to operator<<. The helper encapsulates a pointer to the previous helper (of type Helper) and to the logger value (of type T), plus a boolean flag active. The helper constructor takes a non const reference to the previous helper, deactivates it and sets itself as the active helper: it will be the one to actually perform the logging action, unless another helper steps in and takes control.
The actual logging is performed in the active helper destructor, which is called at the end of the logging statement. The deactivation of all the encapsulated helpers assures that only one active helper exists at any time. The logging procedure involves locking a global mutex, writing to a log stream and then unlocking it, so that multiple logging statements do not overlap.
This solution works for logging temporary objects as well, because they are guaranteed to be destroyed in the inverse order of their creation: since the helper objects will always be created later, their destructors will be called before the destruction of the temporaries, so they are still valid when they are forwarded to the actual stream.

Here is the code, simplified to avoid dependencies.


Follow

Get every new post delivered to your Inbox.