singleton dependencies

The singleton pattern, while not without debate[1], has many friends. Some reasons for that may be because it’s convenient to use, easy to understand and seemingly easy to implement.

The subject I want to discuss today is singleton dependencies in C++.

the problem

Say you have a singleton implementation that you use to retrieve pooled database connections. Imagine you have yet another singleton that handles object serialization to a database. Depending on the order of initialization of both singletons, the database connection pool might have already been destroyed even though you still require it during the destruction of your singleton which handles the serialization[2]. The C++ standard does not define an order of initialization of global static objects, but it does specify that the objects have to be destroyed in the reverse order of their creation. If we could assure that the database singleton object would be created before the serialization object, it would be still around during the shutdown of our serialization singleton.

a basic singleton implementation

A singleton implementation that I’m quite fond of is the “Meyers Singleton[3].

class my_singleton {
public:
  static my_singleton& instance() {
    static my_singleton instance;
    return instance;
  }
private:
  my_singleton() {};
  // since the destructor is also private we don't have to
  // declare the copy constructor as private but it underlines the idea.
  my_singleton( const my_singleton& );
  ~my_singleton() {};
};

The object will be instantiated by the first usage of the singleton (lazy instantiation). While it’s not thread-safe[4] you could work around that by initializing the singleton before you create multiple threads or use an alternative implementation. Since we use lazy instantiation (the object my_singleton will only be created when you first call the my_singleton::instance() class method) we elegantly navigated ourselves around the unordered initialization problem. The problem with the first constructed, last destroyed problem however still persists. We get to that later …

a take on a generic solution

The following is my approach to an C++ Template for this pattern. Here I use a template idiom known as the CRTP (Curiously Recurring Template Pattern) to inherit the singleton template from the class that we want to implement the singleton pattern.

template<class derived_T>
class singleton {
public:
  static derived_T& instance() {
    static derived_T instance;
    return instance;
  }
protected:
  singleton () {};
  singleton( const singleton& );
  ~singleton () {};
};
 
// example of an class using this pattern.
// we use CRTP to inherit from the singleton template.
class my_consumer : public singleton<my_consumer> {
  friend class singleton<my_consumer>;
public:
  void do_something_amazing() {};
private:
  my_consumer() {}
};

another look at the problem

let’s now see how our example from the beginning would look in code:

 
// -- header file 1
#include <singleton.hpp> // our singleton template
 
class database_connection_pool : public singleton<database_connection_pool> {
  friend class singleton<database_connection_pool>;
public: 
  shared_connection_type connect( const std::string& connection_string ) {
     // ...
  }
private:
  database_connection_pool() {}
};
 
// -- header file 2
#include <singleton.hpp> // our singleton template
#include "database_connection_pool.hpp"
 
class object_serializer : public singleton<object_serializer> {
  friend class singleton<object_serializer>;
public:
  template<class object_T>
  void serialize( const object_T& obj ) {
    database_connection_pool& db_pool = database_connection_pool::instance();    
    // ...
  }
 
private:
  object_serializer() {}
};

in case the object_serializer is called first from the code it will also be the last object to be destroyed. If we wanted to serialize a set of registered objects from within the destructor of the object_serializer we would then have to live with the fact that the database_connection_pool would be re-constructed for this one time serialization. Which might not be a terrible thing – but then again it would not be your singleton again, right? While the pattern description only limits the number of instances to one, in my opinion you should also always have to interact with the ‘same’ object. Imagine now that you might not be dealing with a connection manager here but an singleton which provides you with pooled memory and functions to retrieve and free memory. Here you might well pass an already freed pointer to a free method of an singleton which is not really the “singleton” you expected it to be.

Now that we have defined our problem, let’s find an solution. Which comes in the form of an policy class.

compile time dependency specification with the help of a policy class

 
namespace policy {
  class no_dependency {
  };
 
  template<class dep1_T>
  class singleton_dependency {
  public:
    singleton_dependency() {
      dep1_T& dep1 = dep1_T::instance();
    }
  };
 
  template<class dep1_T, class dep2_T>
  class singleton_dependency_2 {
  public:
    singleton_dependency_2() {
      dep1_T& dep1 = dep1_T::instance();
      dep2_T& dep2 = dep2_T::instance();
    }
  };
}
 
template<class derived_T, class dependency_T = policy::no_dependency >
class singleton {
public:
  static derived_T& instance() {
    static dependency_T dependency;
    static derived_T instance;
    return instance;
  }
protected:
  singleton () {};
  singleton( const singleton& );
  ~singleton () {};
};

what has changed?
the default behavior of our singleton class hasn’t changed really. Because we pass the policy::no_dependency class as a default template parameter we won’t have to change our existing code. The method singleton::instance has also changed slightly, there is an additional call to the default created constructor of the no_dependency class that the compiler will most likely be able to optimize away from the code. But if we wanted to express now that there is a dependency relationship, we could easily do so by passing the additional template parameter along. As we can see in the next example:

 
class call_before_test : public singleton<call_before_test> {
  friend class singleton<call_before_test>;
public:
  // ...
private:
  call_before_test() {
    std::cout << "before_test constructor called" << std::endl;
  }
};
 
class test : public singleton<test, policy::singleton_dependency<call_before_test> > {
  friend class singleton<test, policy::singleton_dependency<call_before_test> >;
public:
  // ...
private:
  test() {
    std::cout << "test constructor called" << std::endl;
  }
};
 
int main( int argc, char * argv[] ) {
  test::instance();
  return 0;
}

you will also be able to create dependency hierarchies with this, just be careful not to create cyclic dependencies.
As you can see from the example if you would try it yourself call_before_test will be instantiated before test.

complete example

#include <iostream>
 
namespace policy {
	class no_dependency {
	};
 
	template<class dep1_T>
	class singleton_dependency {
	public:
		singleton_dependency() {
			dep1_T& dep1 = dep1_T::instance();
		}
	};
 
	template<class dep1_T, class dep2_T>
	class singleton_dependency_2 {
	public:
		singleton_dependency_2() {
			dep1_T& dep1 = dep1_T::instance();
			dep2_T& dep2 = dep2_T::instance();
		}
	};
}
 
template<class derived_T, class dependency_T = policy::no_dependency >
class singleton {
public:
	static derived_T& instance() {
		static dependency_T dependency;
		static derived_T instance;
		return instance;
	}
protected:
	singleton () {};
        singleton( const singleton& );
	~singleton () {};
};
 
class call_before_test : public singleton<call_before_test> {
	friend class singleton<call_before_test>;
public:
	// ...
private:
	call_before_test() {
		std::cout << "call_before_test constructor called" << std::endl;
	}
	~call_before_test() {
		std::cout << "call_before_test destructor called" << std::endl;
	}
};
 
class test : public singleton<test, policy::singleton_dependency<call_before_test> > {
	friend class singleton<test, policy::singleton_dependency<call_before_test> >;
public:
	// ...
private:
	test() {
		std::cout << "test constructor called" << std::endl;
	}
	~test() {
		std::cout << "test destructor called" << std::endl;
	}
};
 
int main( int argc, char * argv[] ) {
	test::instance();
	return 0;
}

sideline discussion

[1] – From an OO perspective one could argue against this pattern that it hides dependencies in the code. It makes also unit testing a challenge since you have to deal with global state.  In my opinion the singleton may be a valid solution for a given problem (logging for example) but it is certainly no silver bullet.

[2] – In C++ global static objects are initialized in undefined order and destroyed in the reverse order of their creation. Since the standard does not define a certain order you can not rely on it. Even when you may get away in assuming a fixed order initialization of static objects in one compilation unit for one given compiler set, the same order for another build environment would be based on sheer luck as would be the correct initialization over multiple compilation units.

[3] – More Effective C++: S.Meyers.

[4] – even though you can’t see it from the C++ code, there is a non-thread-safe test to check if the static my_singleton instance; needs to be initialized or not as shown in the assembly output below:

Further reading:
- Thread-safe lazy singleton template class – a thread safe singleton class based on boost library support.
- C++ and the Perils of Double-Checked Locking – a interesting paper that discusses some problems with this pattern when it comes to multi-threading.
- Cleary, Stephen. boost/pool/detail/singleton.hpp. 2000. 16 Mar 2009


About this entry