Boost logo

Boost :

From: Pierre-Jules Tremblay (boost_at_[hidden])
Date: 2008-01-16 09:24:37


On Jan 16, 2008 3:15 AM, Tobias Schwinger <tschwinger_at_[hidden]> wrote:
> thank you for your review.

You are most welcome. Thank you for your response to my comments.

> > For instance, the design
> > could be made more flexible by allowing thread-safety to be specified as a
> > policy (with appropriate default) or by delegating the responsibility to the
> > wrapped type.
>
> OK, FWIW policies complicate things. And what's their benefit here?

In some cases, policies do complicate things. For instance, while I
have marveled at the Loki Singleton implementation, it is at one
extreme of the general-purpose design spectrum and I'm not willing to
pay the price (in complexity). I find your design is, on the other
hand, at the special-purpose end of that spectrum, and I'm not sure
that's necessary.

> > If BOOST_HAS_THREADS is defined, it looks as though I have no
> > choice but to use mutexed instantiation and/or access. If I'm not
> > interested in synchronised access, then the lease interface is useless.
>
> Wrong:
>
> The lease interface is useful to improves performance. The test whether
> the Singleton has been initialized (which requires synchronization) can
> be performed only once.

The test whether the Singleton has been initialized does not require
synchronisation if you are not in an MT context or if the MT context
is handled elsewhere in the design. The performance improvement is
nil when compared to Meyer's singleton, which is the obvious choice in
a single-thread context. What I'm asking for is the opportunity to
select the simplest, most efficient implementation I can get away with
while keeping the interface generic.

I see another argument in favour of a "customizable" synchronisation
mechanism: potential for deadlocks. If there are any circular
dependencies between singletons then you need some kind of lock
restriction mechanism to catch them. You may tell me that having
singletons depend on each other this way is "bad design" and you would
be right, but bad designs are part of life ;-) In practice, I find
that as soon as you allow singletons to creep into a design, they
start to depend on each other.

> > The solution to the OOI problem does not scale, and I would go as far as
> > saying that it doesn't work in practice. In my experience, it's a constant
> > maintenance nightmare to try and keep the various slot assignments in the
> > correct order (I have to deal with a large number of singletons; yes that is
> > a problem in and of itself - this library will do nothing to discourage
> > it).
>
> You must have misunderstood the docs. OOI is not done with slots. The
> slots are to prevent unnecessary resurrection during destruction.

Okay, I should have said "OOD" (order of destruction) instead. So
reading the documentation:

 Singleton instances are normally destroyed in reverse order of their
construction, that is for a group of Singletons with their integral
DisposalSlot template arguments being equal, where the destruction of
these groups is ordered by the ascending DisposalSlot values. We
could raise the DisposalSlot value of global_log from the previous
examples to make sure it outlives other singletons that use 0 (the
default): (...)

That, to me, sounds like the slot mecanism is for handling
dependencies, in which case one must be careful in selecting which
singletons fit in which slot.

> > The only scheme I've personally had any success with, so far, involves
> > some form of reference counting, i.e. singletons that depend on other
> > singletons do so explicitly (by incrementing the other's refcount on
> > construction; the singletons are destroyed when their refcount goes to
> > zero).
>
> You might have gotten away with it in practice, but introducing this
> kind of coupling seems really bad design to me.

The coupling is there anyways (in the singleton's client code), but it
is only implicit: that's the problem with global variables and
singletons are no different in that respect. What I described only
makes the coupling explicit in the singleton's interface. It's not as
bad as it may sound: think shared_ptr with a forward declaration of
the single-instanced type.

> > Another reason why the proposed OOI solution fails in practice is that other
> > singletons are not a singleton's only dependency: client code ( e.g. objects
> > that reference the singleton) are dependencies as well and may affect the
> > order of destruction.
>
> What is the "proposed OOI solution" you are talking about?

Yours, although it appears I had mislabeled it. I'll think up a
concrete example and write back.

> > You just can't assume the singleton manager will be
> > the last thing to go - there may be other globals.
>
> It's the "we should remove pointers from C++ because one can dereference
> NULL" kind-of argumentation.

That's a little unfair, but I think I see what you mean. In that
case, I think you need to improve the documentation to clearly express
the limitations of the design, e.g. "singletons cannot have
dependencies on globals or singletons not of this library, and
vice-versa".

> > BTW I find the very idea
> > of being able to "force" singleton destruction quite scary, but I haven't
> > looked at the implementation details.
>
> It's necessary, as long as C++ runs on top of ABIs that don't support
> code to be run automatically when a dynamic library is unloaded and I
> can assure you that running code in an unloaded, dynamic library is a
> lot scarier :-).

Admittedly, I haven't had to deal with that use case in a long time,
so I probably shouldn't comment on it.

> > Finally, this may constitute a minority opinion but I like to consider
> > global access and single instance as orthogonal concepts. One may want to
> > ensure a resource is only instantiated once without necessarily providing
> > global access to that resource.
>
> So Singletons should be dynamic arrays in your opinion?

I'm not sure what you mean, and I haven't had coffee yet so perhaps
that's why ;-). How do dynamic arrays help separate the concepts of
preventing a second instantiation and global access to the first
instance?

Cheers,

pj


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