Hello, everybody.

This week, more content from Implementing QuantLib: QuantLib’s implementation of the much maligned Singleton pattern. And no, I didn’t say unjustly maligned.

Mandatory plug: there are still places available for my next Introduction to QuantLib Development course. If you want to hear me describe the architecture of the library and then put you through the paces with coding exercises, that’s the place to be. Tell it to whoever manages your training budget. More info in the banner above.

Subscribe to my Substack to receive my posts in your inbox, or follow me on Twitter or LinkedIn if you want to be notified of new posts, or subscribe via RSS if you’re the tech type: the buttons for all that are in the footer. Also, I’m available for training, both online and (when possible) on-site: visit my Training page for more information.

The Singleton pattern

The Gang of Four devoted the first part of their book [1] to creational patterns. While logically sound, this choice turned out to have an unfortunate side effect: all too often, overzealous programmers would start to read the book and duly proceed to sprinkle their code with abstract factories and singletons. Needless to say, this does less than intended for the clarity of the code.

You might suspect the same reason for the presence of a Singleton class template in QuantLib. (Quite maliciously, I might add. Shame on you.) Fortunately, we can base our defense on version-control logs; such class was added to the library later than, say, Observer (a behavioral pattern) or Composite (a structural one).

Our default implementation is shown in the following listing.

    template <class T>
    class Singleton : private noncopyable {
      public:
        static T& instance();
      protected:
        Singleton();
    };

    #if defined(QL_ENABLE_SESSIONS)
    // the definition must be provided by the user
    Integer sessionId();
    #endif

    template <class T>
    T& Singleton<T>::instance() {
        static map<Integer, shared_ptr<T> > instances_;
        #if defined(QL_ENABLE_SESSIONS)
        Integer id = sessionId();
        #else
        Integer id = 0;
        #endif
        shared_ptr<T>& instance = instances_[id];
        if (!instance)
            instance = shared_ptr<T>(new T);
        return *instance;
    }

It’s based on the Curiously Recurring Template Pattern, that I described in a previous post; to be a singleton, a class C needs to inherit from Singleton<C>, to provide a private constructor taking on arguments, and to make Singleton<C> a friend so that it can use it. You can see an example in the Settings class.

As suggested by Scott Meyers [2], the map holding the instances (bear with me) is defined as a static variable inside the instance method. This prevents the so-called static initialization order fiasco, in which the variable is used before being defined, and in C++11 it has the additional guarantee that the initialization is thread-safe (even though that’s not the whole story, as we’ll see).

Now, you might have a few questions; e.g., why a map of instances if this is supposed to be a singleton? Well, that’s because having a single instance might be limiting; for instance—no pun intended—you might want to perform simultaneous calculations on different evaluation dates. Thus, we tried to mitigate the problem by allowing one Singleton instance per thread. This is enabled by a compilation flag, and causes the instance method to use the #if branch in which it gets an id from a sessionId function and uses it to index into the map. If you enable per-thread singletons, you must also provide the latter function; it will probably be something like

    Integer sessionId() {
        return /* `some unique thread id from your system API` */ ;
    }

in which you will identify the thread using the functions made available by your operating system (or some threading library), turn the identifier into a unique integer, and return it. In turn, this will cause the instance method to return a unique instance per each thread. If you don’t enable the feature, instead, the id will always ever be 0 and you’ll always get the same instance. In this case, you probably don’t want to use threads at all—and in the other case, you obviously do, but you have to be careful anyway: see the discussion in my post on global settings.

You might also be asking yourself why I said that this is our default implementation. Nice catch. There are others, which I won’t show here and which are enabled by a number of compilation flags. On the one hand, it turned out that the static-variable implementation didn’t work when compiled as managed C++ code under .NET (at least with older Visual Studio compilers), so in that case we switch it with one in which the map is a static class variable. On the other hand, if you want to use a global Singleton instance in a multi-threaded setting, you want to make sure that the initialization of the Singleton instance is thread-safe (I’m talking about the instance itself, not the map containing it; it’s where the new T is executed). This requires locks, mutexes and stuff, and we don’t want to go near any of that in the default single-threaded setting; therefore, that code is behind yet another compilation flag. You can look at it in the library, if you’re interested.

Your last question might be whether we should have a Singleton class at all—and it’s a tough one. Again, I refer you to the previous discussion of global settings. At this time, much like democracy according to Winston Churchill, it seems to be the worst solution except for all the others.

Bibliography

[1] E. Gamma, R. Helm, R. Johnson and J. Vlissides, Design Patterns: Element of Reusable Object-Oriented Software. Addison-Wesley, 1995.

[2] S. Meyers, Effective C++, 3rd edition. Addison-Wesley, 2005.