
Yay, I finally got the singleton working with allocation and lifetime policies, in addition to being in CRTP form. I know that threading policies still remain, however I would like an opinion on what I have so far. A major difference from Loki is that my lifetime policy needs to know about the allocation policy in order for dependencies to be possible to implement. The code is available here: http://www.ezequal.com/chaos/libs/policy_singleton.h After I am assured that the structure of the code is pretty much correct, i will begin adding additional policies, such as the longevity lifetime that Loki supports. If there are policies that Loki doesn't provide that might be widely useful, please mention them so that they can be incorporated. I look forward to any and all feedback. -Jason

At 05:01 AM 1/9/2005, Jason Hise wrote:
... A major difference from Loki is that my lifetime policy needs to know about the allocation policy in order for dependencies to be possible to implement.
Andre argues strongly that policies should be orthogonal, and I suppose designs are a bit cleaner (and documentation easier) if there is no interaction between policies. But orthogonality does make it difficult or impossible to provide certain features, so it doesn't bother me if policies interact in well documented ways. --Beman

Beman Dawes wrote:
Andre argues strongly that policies should be orthogonal, and I suppose designs are a bit cleaner (and documentation easier) if there is no interaction between policies. But orthogonality does make it difficult or impossible to provide certain features, so it doesn't bother me if policies interact in well documented ways.
It would seem artificial to me in the first place to try to pretend that an object's lifetime is completely independent of its allocation methods, as allocation/deallocation is how a singletons lifetime generally begins and ends. In fact, I'm starting to wonder if allocation should even be a policy passed to the singleton itself, when allocation might be better suited as a policy just for lifetime policies. -Jason

"Jason Hise" wrote:
Small note: there's one try/catch block that can be replaced with RAII. It would make system compilable even when exceptions are disabled. /Pavel

Pavel Vozenilek wrote:
Small note: there's one try/catch block that can be replaced with RAII. It would make system compilable even when exceptions are disabled.
Actually, that try block exists for only the specific case when the constructor throws... I'm not sure how it could be implemented via RAII, as dependencies should only be decremented upon failure. The dtor itself, and thus ReleaseDependency, should not be called if new or the ctor throws. -Jason

"Jason Hise" wrote:
Actually, that try block exists for only the specific case when the constructor throws... I'm not sure how it could be implemented via RAII, as dependencies should only be decremented upon failure. The dtor itself, and thus ReleaseDependency, should not be called if new or the ctor throws.
struct undoer_t { int* value; undoer_t(int* val) value(val) {} ~undoer_t() { if (value) --*value; } void dismiss() { value = 0; } } undoer(&dependents); ..... possibly throwing operation undoer.dismiss(); /Pavel

Pavel Vozenilek wrote:
struct undoer_t { int* value; undoer_t(int* val) value(val) {} ~undoer_t() { if (value) --*value; } void dismiss() { value = 0; } } undoer(&dependents);
..... possibly throwing operation
undoer.dismiss();
Ok, that makes sense. I'll implement that change. Thanks!

At 16:56 09.01.2005 +0100, you wrote:
Actually, that try block exists for only the specific case when the constructor throws... I'm not sure how it could be implemented via RAII, as dependencies should only be decremented upon failure. The dtor itself, and thus ReleaseDependency, should not be called if new or the ctor throws.
struct undoer_t { int* value; undoer_t(int* val) value(val) {} ~undoer_t() { if (value) --*value; } void dismiss() { value = 0; } } undoer(&dependents);
..... possibly throwing operation
undoer.dismiss();
Wouldn't it be easier to change AddDependency to something like the following: static void AddDependency ( ) { static bool first = true; if ( first ) { s_inst = static_cast < T * > ( A :: Create ( ) ); dependents = 0; first = false; } ++dependents; } Thomas Beckmann

Thomas Beckmann wrote:
Wouldn't it be easier to change AddDependency to something like the following:
static void AddDependency ( ) { static bool first = true;
if ( first ) { s_inst = static_cast < T * > ( A :: Create ( ) ); dependents = 0; first = false; } ++dependents; }
The problem is that this makes recreating the singleton impossible... you lose the phoenix effect. Also, creating the singleton might inadvertently result in creating something else that creates something else that has a singleton dependency. If such a thing happens, dependents should be in a correct state ( aka incremented ) before create is called. -Jason

Hello, Jason/all. I find the discussion around the new/improved Singleton template very exciting. Perhaps a month ago, I'd written a Singleton class template in a manner similar to Jason's initial approach (though not *nearly* as cool/customizable). I.e. template < typename T, int Longevity = static_cast<int>( T::Longevity ) > struct Singleton : public SingletonBase, public T {...}; My approach was: 1. Have a single SingletonRegistry that would keep pointers to all Singleton instances (well, actually, SingletonBase instances. SingletonBase is not a class-template.) 2. Each instance has a longevity-int associated with it. At destruction-time, we sort the singleton-instances based on their relative longevities, and destroy the objects in order. It's kinda up to the "client" of Singleton<T> to figure out the collaboration between her classes, and assign longevity-values to her classes. 3. Singleton<T> instances are "registered" with the SingletonRegistry, by its constructor. 4. Singleton<T>::~Singleton() lets the registry know that the instance may be destroyed. The SingletonRegistry destroys the instance if all singletons with a lesser longevity have already been marked for destruction. (I guess that's simple mark-and-sweep.) I'd be honoured and grateful if anyone has comments on this approach. I'd be happy to furnish details/code if anyone's interested/cares. I have a couple of (naïve?) questions regarding the new approach. Please bear with me: 1. Why was the old approach abandoned in favour of CRTP? The reason I went with the above was that I wanted Singleton<T>& to be able to replace T&. I wanted the Singleton template to fit around an existing class definition, as inobtrusively as possible. Would somebody kindly clarify? 2. At least in Jason's first version, the Singleton class-template had a static Singleton<T> instance. Wouldn't that cause the instance to *always* be instantiated at load-time? I used a function-static instead, as follows: /*private*/ Singleton<T>::Singleton() : SingletonBase( Longevity ), T() // <--- Assuming Default Constructor. Help! { //... SingletonRegistry::getInstance().registerSingleton( this ) ; } /*static*/ T& Singleton<T>::getInstance() { static T* pInstance = new Singleton<T>() ; return *pInstance ; } The instance won't be created until required. A possible problem with using a function-static is that I might need double-checked locking to ensure that multiple threads don't construct the same instance (multiply). IMHO, that's not a problem here since pInstance is a static. I'm guessing most reasonable compilers ensure that the static's constructor is called only once, via double-checked locking. (I use aCC 5.56 on HPUX 11i. I have confirmation at least for aCC.) I'm just piggy-backing on that. Comments? Would that break on other compilers? 3. Say an application uses multiple shared libs. Say Singleton<MyClass> is used in more than one library. The definition of the static singleton-instance is in the template header (assuming that we're not using template exports, and all this stuff is inline). There's a good chance that the definition of Singleton<MyClass> might be generated multiply in different libraries of the same app. Won't that mean that there will be more than 1 instance of Singleton<MyClass>? I'm not sure how to get around this right now. Ideas? 4. Will there be issues with dependencies across shared libraries? Say Singleton<MyClass> depends on Singleton<Logger> because MyClass::~MyClass() needs to log stuff. If these are in separate libraries, won't the order in which the libraries are unloaded pose a problem? In my specific application, the libraries are loaded using dlopen() and unloaded using dlclose(). It involves some libraries being unloaded/reloaded several times, while other libraries remain loaded much longer. In my code, I use static variables (associated with each Singleton instance) to "detect" that a library is being unloaded, and "unregister" that lib's Singletons from the SingletonRegistry. I'm still exploring Jason's implementation, to see how this is dealt with... Or if this is even a problem. I look forward to comments. If anyone would like clarifications/code, I'd be honoured. With best regards, Mithun -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jason Hise Sent: Sunday, January 09, 2005 3:32 PM To: boost@lists.boost.org Subject: [boost] Singleton Yay, I finally got the singleton working with allocation and lifetime policies, in addition to being in CRTP form. I know that threading policies still remain, however I would like an opinion on what I have so far. A major difference from Loki is that my lifetime policy needs to know about the allocation policy in order for dependencies to be possible to implement. The code is available here: http://www.ezequal.com/chaos/libs/policy_singleton.h After I am assured that the structure of the code is pretty much correct, i will begin adding additional policies, such as the longevity lifetime that Loki supports. If there are policies that Loki doesn't provide that might be widely useful, please mention them so that they can be incorporated. I look forward to any and all feedback. -Jason _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Mithun R K wrote:
Hello, Jason/all.
I find the discussion around the new/improved Singleton template very exciting.
Perhaps a month ago, I'd written a Singleton class template in a manner similar to Jason's initial approach (though not *nearly* as cool/customizable). I.e.
template < typename T, int Longevity = static_cast<int>( T::Longevity ) > struct Singleton : public SingletonBase, public T {...};
My approach was:
1. Have a single SingletonRegistry that would keep pointers to all Singleton instances (well, actually, SingletonBase instances. SingletonBase is not a class-template.) 2. Each instance has a longevity-int associated with it. At destruction-time, we sort the singleton-instances based on their relative longevities, and destroy the objects in order. It's kinda up to the "client" of Singleton<T> to figure out the collaboration between her classes, and assign longevity-values to her classes. 3. Singleton<T> instances are "registered" with the SingletonRegistry, by its constructor. 4. Singleton<T>::~Singleton() lets the registry know that the instance may be destroyed. The SingletonRegistry destroys the instance if all singletons with a lesser longevity have already been marked for destruction. (I guess that's simple mark-and-sweep.)
I'd be honoured and grateful if anyone has comments on this approach.
This is interesting. The main problem that your code introduces is in the SingletonRegistry, by keeping pointers to the non-template base. By making this non-template base mandatory, I would think that making destructors virtual would become mandatory, and introduce much overhead. The method I plan to use will keep pointers to static Create and Destroy methods (which the templated LongevityLifetime will introduce). This way the SingletonRegistry can maintain a stack of nodes that have pointers to the create and destroy methods, without needing to actually have access to the singleton instance itself.
I have a couple of (naïve?) questions regarding the new approach. Please bear with me:
1. Why was the old approach abandoned in favour of CRTP? The reason I went with the above was that I wanted Singleton<T>& to be able to replace T&. I wanted the Singleton template to fit around an existing class definition, as inobtrusively as possible. Would somebody kindly clarify?
The two problems mentioned with my previously used approach (anyone correct me if I missed one) was that it introduced virtual functions, and that typing out Singleton < Important > was harder than just writing out Important. In my old model it would have made it illegal to create an instance of Important, and thus a singleton around that type wouldn't really be an unobtrusive wrapper, in that it would disable any code already using the class as a non singleton. The new method simply cuts out some unnecessary syntax.
2. At least in Jason's first version, the Singleton class-template had a static Singleton<T> instance. Wouldn't that cause the instance to *always* be instantiated at load-time?
Au contraire! In fact, the original version had a static *pointer* to the singleton. What was causing the singleton to always be instantiated before main was the static dependency, which I quickly eliminated upon discovering that this behavior is not always desirable.
3. Say an application uses multiple shared libs. Say Singleton<MyClass> is used in more than one library. The definition of the static singleton-instance is in the template header (assuming that we're not using template exports, and all this stuff is inline). There's a good chance that the definition of Singleton<MyClass> might be generated multiply in different libraries of the same app. Won't that mean that there will be more than 1 instance of Singleton<MyClass>? I'm not sure how to get around this right now. Ideas?
I suspect that the one definition rule would require the linker to see that the names are identical. Then the linker could verify that the definitions are identical or assume that they are identical and ignore one. However I could be completely wrong about this, so if I am someone please correct me.
4. Will there be issues with dependencies across shared libraries? Say Singleton<MyClass> depends on Singleton<Logger> because MyClass::~MyClass() needs to log stuff. If these are in separate libraries, won't the order in which the libraries are unloaded pose a problem?
Perhaps the lifetime of the dlls themselves could be managed with singletons? When the dll's dtor is called, it could unregister the relevant classes and unload the dll. -Jason

----- Original Message ----- From: "Jason Hise" <chaos@ezequal.com> To: <boost@lists.boost.org> Sent: Wednesday, January 12, 2005 11:07 AM Subject: Re: [boost] Singleton [snip]
My approach was:
1. Have a single SingletonRegistry that would keep pointers to all Singleton instances (well, actually, SingletonBase instances. SingletonBase is not a class-template.) 2. Each instance has a longevity-int associated with it. At destruction-time, we sort the singleton-instances based on their relative longevities, and destroy the objects in order. It's kinda up to the "client" of Singleton<T> to figure out the collaboration between her classes, and assign longevity-values to her classes. 3. Singleton<T> instances are "registered" with the SingletonRegistry, by its constructor. 4. Singleton<T>::~Singleton() lets the registry know that the instance may be destroyed. The SingletonRegistry destroys the instance if all singletons with a lesser longevity have already been marked for destruction. (I guess that's simple mark-and-sweep.)
I'd be honoured and grateful if anyone has comments on this approach.
At your command :-) Apologies for the delayed response but I was waiting for this to develop. Instead it seems to have gone elsewhere. After struggling with the issue of ctor+dtor of C++ globals for some time, I wonder at the efficacy of your own intentions, WRT correct dtor of singletons. While I can see where it is headed and can imagine that it will solve a set of problems, does it solve the typical problem? Assigning some ordering "longevity-int" is creating another "model of destruction". This is different to the CRT model and more significantly, configurable. The perfect ordering of global ctor+dtor is runtime dependent, i.e. the sequence of ctor's and dtor's alters from one execution to another. Here's one instance of related research by others; http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13 If your model is different to the "real" model (ctor+dtor sequence is runtime dependent), what will you achieve with it? If someone wth a dtor dependency issue discovers your "longevity-int" feature, applies it to a complex codebase only to discover that the true problem is outside the domain of an "ordering ints" strategy, is the wasted effort entirely their fault? A ridiculous question posed to make a point. Only hoping to reduce your workload. Developing the singleton template is starting to look like a real job. Cheers, Scott

Hello, Scott/Jason/All. Thank you for having looked at this approach. Scott, I'm not entirely sure I've understood everything you've said... I apologise if I've not made my approach clear. I'm afraid I might have messed up in explaining it. <quote> While I can see where it is headed and can imagine that it will solve a set of problems, does it solve the typical problem? [snip] This is different to the CRT model... </quote> What does one mean by the "typical problem"? And by "the CRT model", do we refer to Jason's new code? <quote> The perfect ordering of global ctor+dtor is runtime dependent, i.e. the sequence of ctor's and dtor's alters from one execution to another. </quote> What I was aiming at was to destroy Singleton objects in a predetermined order, based on the longevity-ints specified, *regardless* of the order of construction. E.g. I'd like my Logger instance to be "alive" until all other Singleton instances are destroyed (because destructors log). I'd like this irrespective of when the first log-request was made (and the Logger was constructed). So I set the Logger's longevity-int to max. Here's how I postpone destruction. The Singleton constructor looks like: /*private*/ Singleton<T>::Singleton() : SingletonBase( Longevity ), T() { static SingletonUnregisterer unregisterer(this) ; // <------------- 1 SingletonRegistry::getInstance().registerSingleton( this ) ; // <-- 2 } /*static*/ T& Singleton<T>::getInstance() { static T* pInstance = new Singleton<T> ; return *pInstance ; } At Line#2, the SingletonRegistry gets a handle to the Singleton instance. Line#1 here is a hack. SingletonUnregisterer is a class whose dtor "unregisters" the Singleton from the SingletonRegistry. The dtor is triggered when the library unloads, or the app exits. Unregistration doesn't necessarily destroy the Singleton immediately. It merely marks the Singleton as ready for destruction. The object won't be destroyed (deleted) until all objects with lesser longevity are marked/destroyed. Since the Logger's longevity is max, it will be destroyed last (after all other Singletons have been destroyed, and all their destructors have finished logging). Similarly, the rest. Please comment? I read the article you pointed me to... With respect, shouldn't the above take care of de-initialization order? <quote> If your model is different to the "real" model (ctor+dtor sequence is runtime dependent), what will you achieve with it? </quote> With the above, I (hoped to) achieve a predetermined order of destruction of static singletons, even if the ctor-sequence is runtime-dependent... <quote> If someone wth a dtor dependency issue discovers your "longevity-int" feature, applies it to a complex codebase only to discover that the true problem is outside the domain of an "ordering ints" strategy, is the wasted effort entirely their fault? A ridiculous question posed to make a point. </quote> I'm really sorry, but I couldn't follow, again... I'm not sure whose fault it is if someone mistakes the "true problem" to be a singleton-deinitialization-problem, when it isn't... (Did I get that right?) I look forward to further comments. Many thanx, Mithun -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Scott Woods Sent: Thursday, January 13, 2005 6:46 AM To: boost@lists.boost.org Subject: Re: [boost] Singleton ----- Original Message ----- From: "Jason Hise" <chaos@ezequal.com> To: <boost@lists.boost.org> Sent: Wednesday, January 12, 2005 11:07 AM Subject: Re: [boost] Singleton [snip]
My approach was:
1. Have a single SingletonRegistry that would keep pointers to all Singleton instances (well, actually, SingletonBase instances. SingletonBase is not a class-template.) 2. Each instance has a longevity-int associated with it. At destruction-time, we sort the singleton-instances based on their relative longevities, and destroy the objects in order. It's kinda up to the "client" of Singleton<T> to figure out the collaboration between her classes, and assign longevity-values to her classes. 3. Singleton<T> instances are "registered" with the SingletonRegistry, by its constructor. 4. Singleton<T>::~Singleton() lets the registry know that the instance may be destroyed. The SingletonRegistry destroys the instance if all singletons with a lesser longevity have already been marked for destruction. (I guess that's simple mark-and-sweep.)
I'd be honoured and grateful if anyone has comments on this approach.
At your command :-) Apologies for the delayed response but I was waiting for this to develop. Instead it seems to have gone elsewhere. After struggling with the issue of ctor+dtor of C++ globals for some time, I wonder at the efficacy of your own intentions, WRT correct dtor of singletons. While I can see where it is headed and can imagine that it will solve a set of problems, does it solve the typical problem? Assigning some ordering "longevity-int" is creating another "model of destruction". This is different to the CRT model and more significantly, configurable. The perfect ordering of global ctor+dtor is runtime dependent, i.e. the sequence of ctor's and dtor's alters from one execution to another. Here's one instance of related research by others; http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13 If your model is different to the "real" model (ctor+dtor sequence is runtime dependent), what will you achieve with it? If someone wth a dtor dependency issue discovers your "longevity-int" feature, applies it to a complex codebase only to discover that the true problem is outside the domain of an "ordering ints" strategy, is the wasted effort entirely their fault? A ridiculous question posed to make a point. Only hoping to reduce your workload. Developing the singleton template is starting to look like a real job. Cheers, Scott _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

----- Original Message ----- From: "Mithun R K" <mithun.radhakrishnan@hp.com> To: <boost@lists.boost.org> Sent: Friday, January 14, 2005 4:34 AM Subject: RE: [boost] Singleton (with Singleton Registry: Clarification)
Hello, Scott/Jason/All.
Thank you for having looked at this approach.
Scott, I'm not entirely sure I've understood everything you've said... I apologise if I've not made my approach clear. I'm afraid I might have messed up in explaining it.
No, you explained it fine. Its the direction and associated ramifications that I was making observations on. Poorly :-)
<quote> While I can see where it is headed and can imagine that it will solve a
set
of problems, does it solve the typical problem? [snip] This is different to the CRT model... </quote>
What does one mean by the "typical problem"? And by "the CRT model", do we refer to Jason's new code?
The "typical problem" is that objects in any substantial application want to be destroyed in a runtime-dependent order. The exact order is driven by what activity occurs during execution. Trying to dictate an order (i.e. longevity-int) onto something that is dynamic is... misdirected. What I am describing here can equally be applied to the default order of dtor imposed by the C runtime (CRT order). Whether the imposed, *fixed* order is CRT or longevity-int it will eventually be the wrong order for some execution path of your application. longevity-int prioritizing may reduce the ordering problem, I cant really say. But it would certainly be a significant thing to implement and maintain. With all that effort, there could be disappointment when an application still crashes on termination. ps: By CRT I mean the order of dtor of global objects imposed by the C runtime.
<quote> The perfect ordering of global ctor+dtor is runtime dependent, i.e. the sequence of ctor's and dtor's alters from one execution to another. </quote>
What I was aiming at was to destroy Singleton objects in a predetermined order, based on the longevity-ints specified, *regardless* of the order of construction. E.g. I'd like my Logger instance to be "alive" until all
other
Singleton instances are destroyed (because destructors log). I'd like this irrespective of when the first log-request was made (and the Logger was constructed). So I set the Logger's longevity-int to max.
Its the pre-determined order that is the problem.
With the above, I (hoped to) achieve a predetermined order of destruction
of
static singletons, even if the ctor-sequence is runtime-dependent...
Again; you do not know the required order of destruction at compile-time.
<quote> If someone wth a dtor dependency issue discovers your "longevity-int" feature, applies it to a complex codebase only to discover that the true problem is outside the domain of an "ordering ints" strategy, is the wasted effort entirely their fault? A ridiculous question posed to make a point. </quote>
I'm really sorry, but I couldn't follow, again... I'm not sure whose fault it is if someone mistakes the "true problem" to be a singleton-deinitialization-problem, when it isn't... (Did I get that right?)
I look forward to further comments.
No worries Mithun. If I havent successfully made my point now then its probably best to just carry on. My observations come from several attempts to impose strategies onto dtor-ordering (and also ctor-ordering). These experiences have been fairly humbling. My favorite technique these days involves something that is known as "function guards" (as per the link provided previously) and "custom dependency work" (hacking). important_object & object1() { static important_object *p = new important_object; return *p; } // Hack example; forces instantiation during CSV static important_object &r = object1(); Cheers, Scott

Scott Woods wrote:
The "typical problem" is that objects in any substantial application want to be destroyed in a runtime-dependent order. The exact order is driven by what activity occurs during execution. Trying to dictate an order (i.e. longevity-int) onto something that is dynamic is... misdirected.
For this "typical problem", wouldn't it make sense to simply use a dependency oriented lifetime? This way there is no need to keep track of the ints across the application, and singletons are created exactly when they are needed and destroyed as soon as they are no longer required. -Jason

From: "Jason Hise" <chaos@ezequal.com> To: <boost@lists.boost.org> Sent: Friday, January 14, 2005 11:59 AM Subject: Re: [boost] Singleton (with Singleton Registry: Clarification)
The "typical problem" is that objects in any substantial application want to be destroyed in a runtime-dependent order. The exact order is driven by what activity occurs during execution. Trying to dictate an order (i.e. longevity-int) onto something that is dynamic is... misdirected.
For this "typical problem", wouldn't it make sense to simply use a dependency oriented lifetime? This way there is no need to keep track of the ints across the application, and singletons are created exactly when they are needed and destroyed as soon as they are no longer required.
Exactly. That is the only "real" solution to the underlying problem. I was conceding something in my recent response to Mithun, i.e. in the absence of a "real" solution the longevity-int-ordering may still offer some value. Personally I remain uncomfortable that it "takes everyones eye off the ball". Maybe its worse. Maybe its more like "playing a beautiful forehand with a ball from a neighbouring court"? Oh dear. Sporting analogies. :-)

----- Original Message ----- From: "Mithun R K" <mithun.radhakrishnan@hp.com> To: <boost@lists.boost.org> Sent: Friday, January 14, 2005 4:34 AM Subject: RE: [boost] Singleton (with Singleton Registry: Clarification)
Hello, Scott/Jason/All.
Thank you for having looked at this approach.
Scott, I'm not entirely sure I've understood everything you've said... I apologise if I've not made my approach clear. I'm afraid I might have messed up in explaining it.
Ah. Re-read a bunch of mail and think I understand the communications difficulty. I (wrongly) assumed you were proposing the ordering of dtor as a solution to a problem. Actually you were presenting this as a feature? If this is correct then my observations are irrelevant. Of course the that doesnt mean my problem goes away. Its just lurking in the background waiting for a software tester to travel a certain execution path. Until then.... Cheers. ps: I suspect that if the underlying problem was solved then the need for something like longevity-int-ordering is obviated? Hmmmmm.

Hello, Jason/All. A couple of clarifications on my questions. <quote> I suspect that the one definition rule would require the linker to see that the names are identical. Then the linker could verify that the definitions are identical or assume that they are identical and ignore one. However I could be completely wrong about this, so if I am someone please correct me. </quote> This is perfectly true when object-files (with multiple template-instantiations) are being linked by the link-editor, when producing the executable/lib. However, my question had more to do with separate instantiations of Singleton<MyClass> in different shared libraries. Since each lib has a separate Singleton<MyClass> definition, won't each lib also have its own singleton-instance? I'm pretty sure the loader won't be stripping out multiple instantiations across shared libraries (well, not on HPUX, anyway). Won't this pose a problem? <quote> Perhaps the lifetime of the dlls themselves could be managed with singletons? When the dll's dtor is called, it could unregister the relevant classes and unload the dll. </quote> The loading/unloading of the dll's isn't really in our control, is it? It's the dynamic-library-loader of the OS that does it. (/usr/lib/libdld.so, on HPUX). This problem is bound to happen on any app with multiple dlls, right? I've to use a hack on HPUX fix this... I'm open to ideas. <quote> By making this non-template base mandatory, I would think that making destructors virtual would become mandatory, and introduce much overhead. The method I plan to use will keep pointers to static Create and Destroy methods (which the templated LongevityLifetime will introduce). </quote> Thank you for looking at my approach... I really appreciate it. Ok, so I shouldn't be introducing a virtual-base for the singletons... If I were to register only Destroy functors with the SingletonRegistry (each knowing how to destroy its Singleton), would that do? That would move the virtual-base out of the Singleton, and into the "SingletonDestroyer" (I'll still need a virtual base, because the SingletonRegistry will need to hold all the Destroyer functors). Will that be any better? With best regards, Mithun -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jason Hise Sent: Wednesday, January 12, 2005 3:37 AM To: boost@lists.boost.org Subject: Re: [boost] Singleton Mithun R K wrote:
Hello, Jason/all.
I find the discussion around the new/improved Singleton template very exciting.
Perhaps a month ago, I'd written a Singleton class template in a manner similar to Jason's initial approach (though not *nearly* as cool/customizable). I.e.
template < typename T, int Longevity = static_cast<int>( T::Longevity )
struct Singleton : public SingletonBase, public T {...};
My approach was:
1. Have a single SingletonRegistry that would keep pointers to all Singleton instances (well, actually, SingletonBase instances. SingletonBase is not a class-template.) 2. Each instance has a longevity-int associated with it. At destruction-time, we sort the singleton-instances based on their relative longevities, and destroy the objects in order. It's kinda up to the "client" of Singleton<T> to figure out the collaboration between her classes, and assign longevity-values to her classes. 3. Singleton<T> instances are "registered" with the SingletonRegistry, by its constructor. 4. Singleton<T>::~Singleton() lets the registry know that the instance may be destroyed. The SingletonRegistry destroys the instance if all singletons with a lesser longevity have already been marked for destruction. (I guess that's simple mark-and-sweep.)
I'd be honoured and grateful if anyone has comments on this approach.
This is interesting. The main problem that your code introduces is in the SingletonRegistry, by keeping pointers to the non-template base. By making this non-template base mandatory, I would think that making destructors virtual would become mandatory, and introduce much overhead. The method I plan to use will keep pointers to static Create and Destroy methods (which the templated LongevityLifetime will introduce). This way the SingletonRegistry can maintain a stack of nodes that have pointers to the create and destroy methods, without needing to actually have access to the singleton instance itself.
I have a couple of (naïve?) questions regarding the new approach. Please bear with me:
1. Why was the old approach abandoned in favour of CRTP? The reason I went with the above was that I wanted Singleton<T>& to be able to replace T&. I wanted the Singleton template to fit around an existing class definition, as inobtrusively as possible. Would somebody kindly clarify?
The two problems mentioned with my previously used approach (anyone correct me if I missed one) was that it introduced virtual functions, and that typing out Singleton < Important > was harder than just writing out Important. In my old model it would have made it illegal to create an instance of Important, and thus a singleton around that type wouldn't really be an unobtrusive wrapper, in that it would disable any code already using the class as a non singleton. The new method simply cuts out some unnecessary syntax.
2. At least in Jason's first version, the Singleton class-template had a static Singleton<T> instance. Wouldn't that cause the instance to *always* be instantiated at load-time?
Au contraire! In fact, the original version had a static *pointer* to the singleton. What was causing the singleton to always be instantiated before main was the static dependency, which I quickly eliminated upon discovering that this behavior is not always desirable.
3. Say an application uses multiple shared libs. Say Singleton<MyClass> is used in more than one library. The definition of the static singleton-instance is in the template header (assuming that we're not using template exports, and all this stuff is inline). There's a good chance that the definition of Singleton<MyClass> might be generated multiply in different libraries of the same app. Won't that mean that there will be more than 1 instance of Singleton<MyClass>? I'm not sure how to get around this right now. Ideas?
4. Will there be issues with dependencies across shared libraries? Say Singleton<MyClass> depends on Singleton<Logger> because MyClass::~MyClass() needs to log stuff. If these are in separate libraries, won't the order in which the libraries are unloaded pose a
I suspect that the one definition rule would require the linker to see that the names are identical. Then the linker could verify that the definitions are identical or assume that they are identical and ignore one. However I could be completely wrong about this, so if I am someone please correct me. problem?
Perhaps the lifetime of the dlls themselves could be managed with singletons? When the dll's dtor is called, it could unregister the relevant classes and unload the dll. -Jason _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

Mithun R K wrote:
...However, my question had more to do with separate instantiations of Singleton<MyClass> in different shared libraries. Since each lib has a separate Singleton<MyClass> definition, won't each lib also have its own singleton-instance? I'm pretty sure the loader won't be stripping out multiple instantiations across shared libraries (well, not on HPUX, anyway). Won't this pose a problem?
Hum. I honestly don't know. Whats interesting is that this may be another reason that the CRTP model is better. The final singleton class used by client code would (probably) not be a templated class (it would just derive from one), and would (most likely) have its implementation compiled into its own discrete unit.
<quote> Perhaps the lifetime of the dlls themselves could be managed with singletons? When the dll's dtor is called, it could unregister the relevant classes and unload the dll. </quote>
The loading/unloading of the dll's isn't really in our control, is it? It's the dynamic-library-loader of the OS that does it. (/usr/lib/libdld.so, on HPUX). This problem is bound to happen on any app with multiple dlls, right? I've to use a hack on HPUX fix this... I'm open to ideas.
Sorry for my naivety, I haven't really done a lot of work involving multiple dlls in C++. My primary experience with such scenarios has been with C# in .NET, where one has the option of using the classes in the System.Reflection namespace to load other assemblies on command.
Thank you for looking at my approach... I really appreciate it.
Ok, so I shouldn't be introducing a virtual-base for the singletons... If I were to register only Destroy functors with the SingletonRegistry (each knowing how to destroy its Singleton), would that do? That would move the virtual-base out of the Singleton, and into the "SingletonDestroyer" (I'll still need a virtual base, because the SingletonRegistry will need to hold all the Destroyer functors).
Actually, you don't need a virtual base... because of the very nature of a singleton (single instance) you can use plain old static functions. Those functions would then be responsible for tracking down and destroying the single instance. -Jason

Hello, Jason/all. I find the discussion around the new/improved Singleton template very exciting. Perhaps a month ago, I'd written a Singleton class template in a manner similar to Jason's initial approach (though not *nearly* as cool/customizable). I.e. template < typename T, int Longevity = static_cast<int>( T::Longevity ) > struct Singleton : public SingletonBase, public T {...}; My approach was: 1. Have a single SingletonRegistry that would keep pointers to all Singleton instances (well, actually, SingletonBase instances. SingletonBase is not a class-template.) 2. Each instance has a longevity-int associated with it. At destruction-time, we sort the singleton-instances based on their relative longevities, and destroy the objects in order. It's kinda up to the "client" of Singleton<T> to figure out the collaboration between her classes, and assign longevity-values to her classes. 3. Singleton<T> instances are "registered" with the SingletonRegistry, by its constructor. 4. Singleton<T>::~Singleton() lets the registry know that the instance may be destroyed. The SingletonRegistry destroys the instance if all singletons with a lesser longevity have already been marked for destruction. (I guess that's simple mark-and-sweep.) I'd be honoured and grateful if anyone has comments on this approach. I'd be happy to furnish details/code if anyone's interested/cares. I have a couple of (naïve?) questions regarding the new approach: 1. Why was the old approach abandoned in favour of CRTP? The reason I went with the above was that I wanted Singleton<T>& to be able to replace T&. I wanted the Singleton template to fit around an existing class definition, as inobtrusively as possible. Would somebody kindly clarify? 2. At least in Jason's first version, the Singleton class-template had a static Singleton<T> instance. Wouldn't that cause the instance to *always* be instantiated at load-time? I used a function-static instead, as follows: /*private*/ Singleton<T>::Singleton() : SingletonBase( Longevity ), T() // <--- Assuming Default Constructor. Help! { //... SingletonRegistry::getInstance().registerSingleton( this ) ; } /*static*/ T& Singleton<T>::getInstance() { static T* pInstance = new Singleton<T>() ; return *pInstance ; } The instance won't be created until required. A possible problem with using a function-static is that I might need double-checked locking to ensure that multiple threads don't construct the same instance (multiply). IMHO, that's not a problem here since pInstance is a static. I'm guessing most reasonable compilers ensure that the static's constructor is called only once, via double-checked locking. (I use aCC 5.56 on HPUX 11i. I have confirmation at least for aCC.) I'm just piggy-backing on that. Comments? Would that break on other compilers? 3. Say an application uses multiple shared libs. Say Singleton<MyClass> is used in more than one library. The definition of the static singleton-instance is in the template header (assuming that we're not using template exports, and all this stuff is inline). There's a good chance that the definition of Singleton<MyClass> might be generated multiply in different libraries of the same app. Won't that mean that there will be more than 1 instance of Singleton<MyClass>? I'm not sure how to get around this right now. Ideas? 4. Will there be issues with dependencies across shared libraries? Say Singleton<MyClass> depends on Singleton<Logger> because MyClass::~MyClass() needs to log stuff. If these are in separate libraries, won't the order in which the libraries are unloaded pose a problem? In my specific application, the libraries are loaded using dlopen() and unloaded using dlclose(). It involves some libraries being unloaded/reloaded several times, while other libraries remain loaded much longer. In my code, I use static variables (associated with each Singleton instance) to "detect" that a library is being unloaded, and "unregister" that lib's Singletons from the SingletonRegistry. I'm still exploring Jason's implementation, to see how this is dealt with... Or if this is even a problem. I look forward to comments. If anyone would like clarifications/code, I'd be honoured. With best regards, Mithun -----Original Message----- From: boost-bounces@lists.boost.org [mailto:boost-bounces@lists.boost.org] On Behalf Of Jason Hise Sent: Sunday, January 09, 2005 3:32 PM To: boost@lists.boost.org Subject: [boost] Singleton Yay, I finally got the singleton working with allocation and lifetime policies, in addition to being in CRTP form. I know that threading policies still remain, however I would like an opinion on what I have so far. A major difference from Loki is that my lifetime policy needs to know about the allocation policy in order for dependencies to be possible to implement. The code is available here: http://www.ezequal.com/chaos/libs/policy_singleton.h After I am assured that the structure of the code is pretty much correct, i will begin adding additional policies, such as the longevity lifetime that Loki supports. If there are policies that Loki doesn't provide that might be widely useful, please mention them so that they can be incorporated. I look forward to any and all feedback. -Jason _______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost

On Tue, 11 Jan 2005 22:30:42 +0530 "Mithun R K" <mithun.radhakrishnan@hp.com> wrote:
1. Have a single SingletonRegistry that would keep pointers to all Singleton instances (well, actually, SingletonBase instances. SingletonBase is not a class-template.)
Sorry for interloping here, but I think boost already provides several mechinisms for doing the same thing without requiring the inheritance hierarchy. For example, you could register boost::function<> objects to create/destroy, or you could require registry as boost::shared_ptr< Whatever >, and store boost::shared_ptr< void >, which already knows how to properly destroy itself, or ... I have not thought too much about your other issues, but you may want to take a look at ACE, and the ACE_Object_Manager (or something like that). It manages objects, and I believe it hooks atexit() to do other destructions. Of course, there are pros/cons to this approach as well, but it is there to look at...
participants (8)
-
beckmann.bremen@t-online.de
-
Beman Dawes
-
Jason Hise
-
Jody Hagins
-
Mithun R K
-
Mithun R K
-
Pavel Vozenilek
-
Scott Woods