The Singleton Concept is a reasonably simple concept. For writing software, the concept of a singleton stipulates that only one instance of a class will be instantiated during run time. All references to an object of a particular class will be to only one instance. The instance is usually created at program startup, often times before 'main', and destroyed at programs end, often after 'main' exits.
Friday, January 2. 2009
Wanted: A Single C++ Singleton
I wish to use the concept of a Singleton in my C++ based trading software for Manager classes which keep track of Providers, Instruments, and Portfolios.
Thinking that the Singleton Design Pattern was simple, I figured I could implement my own flavour. But I decided to do some research first. It turns out there are simple ways, complicated ways, and controversial ways.
From the controversial side, some consider using Singletons as less than desirable, as the concept introduces global state, which in turn reduces modularity, compartmentalization, and as a consequence increases the complexity of testing. These are valid reasons, and I see it being applicable to situations where a programmer uses Singletons for small objects or built-in data types.
In my situation, I wish to form Singletons of larger self-contained classes. It doesn't make logical sense to have multiple managers, and as such, the Singleton concept enforces/implmements my need for singleton managers.
With the Boost Libraries being as comprehensive and well written as they are, I figured they should offer up a good singleton of a Singleton implementation. Nope. In doing a search through the library, I find about four or six or more different flavours of singleton.hpp, and nothing in the 'common areas' of the library:
- boost/serialization/singleton.hpp: uses boost::noncopyable, has medium multi-threading capability, and contains some .dll dependencies
- boost/log/detail/singleton.hpp: uses boost::noncopyable, is a simpler class, not sure if it is thread safe, and makes use of #defines like BOOST_ONCE_INIT
- boost/pool/detail/singleton.hpp: a simple, self-contained class designed for instantiation before main, basically a type of Meyer's Singleton but using a template mechanism
- boost/thread/detail/singleton.hpp: a very minimalistic singleton
There are notes in some locations indicating that these shouldn't be used as they are essentially 'library internal' routines and are subject to non-documented changes.
hmmm, maybe Singletons are complicated. Alex Ott's Blog mentioned that there was actually a Singleton submission (documentation) to Boost back in the beginning of 2008. The submission promised to handle single threaded and multi-threaded implementations of the Singleton Pattern. It was rejected. Reviewers wanted to see a more modularized approach. The submitter indicated that he has/had run out of time to do so. In reading the review thread, a number of writers didn't like the complexity of the Loki library, and thus the Boost submission took a different tact. I'm of an impression that the library submission would have a good change of succeeding if it followed the 'programming by policy' method used in Loki. Under the hood there is some complexity, but to the user, the interface is clean and modular. For those interested in the submission code, It resides mouldering in the sandbox.
Loki, which was started by Andrei Alexandrescu in his book on "Modern C++ Design", has a Singleton implementation, but no on-line documentation. I went into his book and I see that he goes into some detail on the design ideas and usage notes regarding his Loki SingletonHolder class. Indeed, he says that there is no single size-fits-all singleton. And when looking at the doxygen class notes, there is a variety of construction, lifetime, and threading template traits available. Perhaps this file could be spruced up and submitted to Boost.
Andrei and Scott Meyers wrote a paper back in September 2004 called C++ and the Perils of Double-Checked Locking. It goes into the gory details of why multi-threaded Singletons are so hard to implement. Much of it has to do with compiler optimizations, and the fact that C++ machine states are defined for single threaded models only. It is interesting to note that implication that C++ is really multi-threaded, from a philosophical and design perspecitve. It has been forced into that world with assemlby code and operating system api work arounds. C++ has been so malleable when it comes to metaprogramming, object oriented programming, and any of a number of other programming paradigms. To fall down on the job of multi-threading may be an indication of the difficulties inherent in moving from single-threading to multi-threading and multi-core processing.
In addition to the library submitted to Boost, another author offers up his version of a Thread-Safe C++ Singleton. His writing indicates he uses the concept of a Phoenix Singleton, a Singleton which can recreate itself. The book Modern C++ Design goes into a description of this.
For a simple, single-threaded, self contained Singleton which manages itself, a C++ Singleton Pattern is available. It uses the Curiously Recurring Template Pattern (CRTP). It uses an override of new and delete but does not use reference counting to keep things straight, which may cause problems in some use cases. It is like a Phoenix Singleton but doesn't really do LIFO type creation/destruction properly.
Scott Meyer's "Effective C++ Third Edition" has a description of what has been termed Meyer's Singleton. It does all the constructor, destructor, and assignment hiding and provides a built-in static method for returning a reference to the object instance. Here is a specific version of The Meyers Singleton.
class InstrumentManager { public: static InstrumentManager &Instance() { static InstrumentManager _InstrumentManager; // local static object initialization return _InstrumentManager; } void BasicMethod( void ); private: InstrumentManager(); // constructor (ctor) is hidden InstrumentManager( InstrumentManager const & ); // copy ctor is hidden InstrumentManager &operator=( InstrumentManager const & ); // assignment operator is hidden ~InstrumentManager() // destructor (dtor) is hidden };
// singleton.h #ifndef __SINGLETON_H #define __SINGLETON_H templateclass CSingleton { public: static T& Instance() { static T _instance; return _instance; } protected: private: CSingleton(); // ctor hidden ~CSingleton(); // dtor hidden CSingleton(CSingleton const&); // copy ctor hidden CSingleton& operator=(CSingleton const&); // assign op hidden }; #endif
In summary, I think I'll end up using the boost::detail::pool as it can be used to wrap general classes without resorting to writing classes as specific Meyers Singletons, which may or may not be a good thing. If, at some point in the future, I get some free time, tackling the Loki Singleton to Boost Singleton conversion might be an interesting learning experience.
See also Singleton Per Thread.