Boost logo

Boost :

From: Mithun R K (mithun_at_[hidden])
Date: 2005-01-11 11:42:41


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_at_[hidden] [mailto:boost-bounces_at_[hidden]]
On Behalf Of Jason Hise
Sent: Sunday, January 09, 2005 3:32 PM
To: boost_at_[hidden]
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


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk