KBattleShip update

March 31, 2007 by pcapriotti

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 by pcapriotti

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 by pcapriotti

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.

The “covariant argument problem”

February 25, 2007 by pcapriotti

Working on KBoard I’ve been forced to face great number of design problems, which I’d say have all been solved quite neatly, with one big exception: the covariant argument problem, hereafter referred as CAP.

This dreaded problem manifests itself when trying to abstract a great amount of functionality from a system using a set of interfaces (i.e. abstract classes with only pure virtual functions) so that client code can add custom behaviour to the system by implementing all these interfaces.
Nothing new, you’d say, that’s exactly the purpose of abstract classes and interfaces, but the difference here is that we have a set of (possibly interdependent) interfaces that we would like to implement at once.
To better explain the situation, I need to set up some names, so suppose you have three interfaces IA, IB, IC, and two different and completely incompatible incarnations A, B, C and U, V, W. Suppose further that IA has a method foo taking an IB as a parameter. When implementing the ABC incarnation in client code, you need to preserve the signature of foo, so you’re forced to accept any IB as its parameter, while of course only B’s have a meaning there. This is the fundamental dilemma of CAP.

The story isn’t new: it’s been studied in great detail by type theorist and even addressed in real programming languages like Eiffel, but the subject is still somewhat controversial and I’m not sure that a clean solution really exists, even accepting a language switch (not that I would second it :)).

Our solution consists in a layer of ugly (and by ugly I mean very ugly) template code which does the work of type conversion and type checking that the compiler is unable to do. The strong point of this solution is that the client never needs to delve inside this messy kludge, and can simply implement the required functionality by creating classes complying to implicit interfaces.

If you are curious to understand how this really works, you can find a short description here, and obviously the code, which is only one header file (but ignore the comments, they’re ancient… yes, I know they should be kept up to date…).

XML configuration files for KDE

February 24, 2007 by pcapriotti

Since KBoard needed a powerful hierarchical configuration system and QSettings was too limited for our needs, we decided to implement an XML-based configuration framework from scratch.
Hence, Settings was born.

Today, I’ve decided to write a bit of documentation for Settings, and to eliminate all references in it to the rest of KBoard, so that other KDE (or Qt) developers not satisfied with QSettings/KConfig can benefit.

You can find the code and a sketched documentation on the kboard wiki.

Java generics and iterators

February 23, 2007 by pcapriotti

The java type system, with the introduction of generics, presents a number of quirks. The following is a situation I’ve recently come across.
Suppose you have an interface IAnimal and a class Cow implementing it. Consider the following java code:

// IFarm.java
interface IFarm extends Iterable {
// …
}

// CowFarm.java
class CowFarm implements IFarm {
private ArrayList<Cow> cows = new ArrayList<Cow>();
public Iterator<IAnimal> iterator() {
// what goes here?!?
}
}

How would you implement the iterator method?
A simple

return cows.iterator();

won’t work, because the java compiler does not consider Iterator<Cow> a subtype of Iterator<IAnimal>.

It turns out that the best way to address the problem is to resort to type erasure and suppress the resulting warning!

Another blogger

February 22, 2007 by pcapriotti

It seems that nowadays having a blog is mandatory for everyone, so here’s mine.