
This post refers to the following code: http://www.ezequal.com/chaos/libs/singleton.h I have developed a templated singleton class which enforces almost every rule of the singleton pattern at compile time. This library provides a very clean, flexible format for client code to implement its own singleton classes which may have dependencies on each other. I have three questions. Does it make any sense to use a template allocator parameter, like the standard container types, to control creation and destruction of my instance, or are new and delete sufficient? Is there any other functionality that should be added? Specifically, is it sufficient to enforce that singletons are created in a specific order before main and destroyed in the reverse order after main (using dependency instances), or should I provide some way to support alternate lifetimes (ex: create on first reference to instance)? Is there any interest in adding this library to Boost?

Is there any other functionality that should be added? Specifically, is it sufficient to enforce that singletons are created in a specific order before main and destroyed in the reverse order after main (using dependency instances), or should I provide some way to support alternate lifetimes (ex: create on first reference to instance)?
Is there any interest in adding this library to Boost?
Would be good for boost to have a neat singleton. Check out Loki's and the recentish discussions in the archives regarding threading issues, particularly w.r.t. the double checked locking pattern for singletons. An optimised singleton implementation in boost would probably make use of portable fencing for concurrency. There is quite a bit more to a singleton pattern to cover most uses. matt. matthurd@acm.org

"CHAOS" <0xchaos@gmail.com> wrote in message news:afccc62905010501325046bba6@mail.gmail.com...
This post refers to the following code: http://www.ezequal.com/chaos/libs/singleton.h
I have developed a templated singleton class which enforces almost every rule of the singleton pattern at compile time. This library provides a very clean, flexible format for client code to implement its own singleton classes which may have dependencies on each other. I have three questions.
We could definitely use a Singleton class in boost, I write enough of them, with enough boilerplate, that it would be very convenient to have a class I can derive from. However, I have several issues with your implementation: 1) I strongly dislike your virtual operator=(const SingletonBase &). Most of the Singletons I use don't have any virtual functions, and I would rather not add any if I don't have to. In your comments you say you only define it to make sure that SingletonBase cannot be instantiated. Keeping the destructor (or all the constructors) non-public has the same effect. 2) It would be easier on users if, instead of Singleton<T> inheriting from T, you reversed it so that T must inherit from Singleton<T> (the curiously recurring template pattern). This would make it possible to communicate in both directions between T and Singleton<T>. It would also make it much easier to turn an existing class into a Singleton. Joe Gottman

Joe Gottman wrote:
1) I strongly dislike your virtual operator=(const SingletonBase &). Most of the Singletons I use don't have any virtual functions, and I would rather not add any if I don't have to. In your comments you say you only define it to make sure that SingletonBase cannot be instantiated. Keeping the destructor (or all the constructors) non-public has the same effect.
2) It would be easier on users if, instead of Singleton<T> inheriting from T, you reversed it so that T must inherit from Singleton<T> (the curiously recurring template pattern). This would make it possible to communicate in both directions between T and Singleton<T>. It would also make it much easier to turn an existing class into a Singleton.
First I should note that I made some changes since the first version I posted, the new version is available at http://www.ezequal.com/chaos/libs/singleton_revised.h. Specifically, the singleton no longer has a static dependency on itself, so client code can control lifetimes much more dynamically. In addition, I made GetInst return a smart pointer containing a dependency so that GetInst will never fail. It looks like I should post some sample client code so that it is clear exactly how my design is intended to be used. It is a bit unusual, but actually very clean and safe: #include <iostream> #include "Singleton.h" using namespace utils; using namespace std; class A : public SingletonBase { public: A ( ) { cout << "A created\n"; } ~ A ( ) { cout << "A destroyed\n"; } void DoSomethingUseful ( ) { cout << "A being useful\n"; } }; class B : public SingletonBase { private: // 1) //Singleton < A > :: Dependency require_a; public: B ( ) { cout << "B created\n"; } ~ B ( ) { cout << "B destroyed\n"; } void DoSomethingUseful ( ) { cout << "B being useful\n"; Singleton < A > :: SingletonPtr instance = Singleton < A > :: GetInst ( ); instance->DoSomethingUseful ( ); } }; // 2) //Singleton < B > :: Dependency require_b; int main ( ) { cout << "Entering main\n"; { // 3) //Singleton < B > :: SingletonPtr instance = Singleton < B > :: GetInst ( ); //instance->DoSomethingUseful ( ); } cout << "Exiting main\n"; return 0; } If both points 2 and 3 stay commented out, no singletons are created. If 2 is uncommented, B will exist for the lifetime of the program. If 1 is also uncommented, A will exist before and after B is created and destroyed. If 2 remains commented but 3 is uncommented, the singletons are created in the scope where the instance is referenced, and destroyed when the scope exits. Singletons would be able to be reincarnated any number of times. The important thing to notice is the safety that is enforced at compile time: A) It is illegal at compile time to have a Singleton < T > where T does not derive from SingletonBase. B) It is illegal at compile time to create an instance of SingletonBase. It is also illegal to create an instance of a derived type, because SingletonBase makes assignment pure virtual, therefore making child classes pure virtual as well. C) Even though Singleton < T > overrides the assignment operator to become non abstract, it still cannot be created by client code because of it's private constructor and destructor. D) The singleton instance cannot be copied; only SingletonPtrs to it can be copied, which essentially just increase the number of dependencies. I cannot think of any way I could have enforced all of this if singleton only acted as a base class.

Is there any other functionality that should be added? Specifically, is it sufficient to enforce that singletons are created in a specific order before main and destroyed in the reverse order after main (using dependency instances), or should I provide some way to support alternate lifetimes (ex: create on first reference to instance)?
Is there any interest in adding this library to Boost?
Well, one thing that would be interesting to support is the ability to force the destruction and/or deconnection of all objects referenced from a singleton... For example, when programming with COM (ActiveX), we might have a bunch of objects created by a singleton that must be destroyed before we call CoFreeUnusedLibraries() and/or CoUninitialize(). Also, with multiples DLLs, we typically need to ensure that all references are destroyed before the system unload the DLL. When there are complex depedencies, the system might not knows which DLL to unload first and if some of them have dynamic links to object in other DLL (via the singleton), the application might crash when exiting. This might also be interesting in some situations like a singleton is associated with a document (or maybe a window). So what is needed to cover such cases is the ability to set the object in a "destroying" state. A solution that could work in some situation would be something similar to: Singleton::Deconnect() { if (object) { object->Deconnect(); } } Well, the way to do the deconnection on the object hold by the singleton would not be an hard-coded member but something that would be settable by a policy class or some other template mean (for example, type trait). Another reason that one might want to be able to control when the destruction occurs is that it can allows all code to be executed from a try/catch block in main (so the application can report the error instead of the OS). Philippe

Philippe Mori wrote:
...what is needed to cover such cases is the ability to set the object in a "destroying" state. A solution that could work in some situation would be something similar to:
Singleton::Deconnect() { if (object) { object->Deconnect(); } }
Well, the way to do the deconnection on the object hold by the singleton would not be an hard-coded member but something that would be settable by a policy class or some other template mean (for example, type trait).
I may be confused, but why couldn't (or shouldn't) this code be taken care of by the singleton's destructor in the derived class? It would seem that the derived singleton is the only thing that could possibly know about the specific things it needs to deallocate, and that a destructor would be a natural place to take care of it. -Jason

Philippe Mori wrote:
...what is needed to cover such cases is the ability to set the object in a "destroying" state. A solution that could work in some situation would be something similar to:
Singleton::Deconnect() { if (object) { object->Deconnect(); } }
Well, the way to do the deconnection on the object hold by the singleton would not be an hard-coded member but something that would be settable by a policy class or some other template mean (for example, type trait).
I may be confused, but why couldn't (or shouldn't) this code be taken care of by the singleton's destructor in the derived class? It would seem that the derived singleton is the only thing that could possibly know about the specific things it needs to deallocate, and that a destructor would be a natural place to take care of it.
-Jason
In some situations, we want to "shutdown" an application while there are still references to the singleton (for exemple static variables) and we want objects to be destroyed sooner that what will happen by default. If it is difficult to guarantee that a singleton will not be used till after a given point (where we want explicit destruction), it might be safer to simply "Deconnect" the object. That is, delete is not yet called but we do some cleanup (particulary removing references to other object (or singleton)). At my previous job we were using a lot of singleton where some where in DLL and others would uses COM (ActiveX) object and since some objects were having reference to others, if we were not forcing a shutdown by calling a function on appropriate singleton object, not every object was destroyed before we call CoFreeUnusedLibrairies or before main was exited and DLL where unloaded by the system. And since with dynamically loaded DLL, the system does not knows depedencies, singletons where destroyed in the order that Windows decides to unload the DLL. The problem would then occurs when while destroying a static object (typically a singleton) that was referencing something in a DLL that the system has unloaded, a crash would occurs. Philippe

Philippe Mori wrote:
In some situations, we want to "shutdown" an application while there are still references to the singleton (for exemple static variables) and we want objects to be destroyed sooner that what will happen by default.
In this case it would seem to me that a ShutDown method should be added to the derived singleton, and called appropriately. Adding a policy to handle this seems unnecessary and redundant, because at most it could only enforce that the singleton have the ShutDown method. Only the derived singleton knows exactly what ShutDown entails, and only classes that refer to that specific type of singleton could possibly know when it would be appropriate to make that function call. -Jason
participants (5)
-
CHAOS
-
Jason Hise
-
Joe Gottman
-
Matt Hurd
-
Philippe Mori