Jon Stewart on 18 Jun 2003 23:10:01 -0000


[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]

Re: [ALACPP] Singleton clarification


> So, I tend to have two problems with singletons, and this case is
> actually a decent example of those problems:
> 
> 1) The "only one instance" notion almost always needs to be qualified,
> and people tend to forget to do that. So, perhaps you have it's
> one-per-object, one-per-thread, one-per-process, one-per-network
> interface, one-per-system, one-per-subnet, etc.


I think the overwhelming default is one-per-process. If it's anything 
else, you should probably stick in an object representing its 
qualification (network, thread, etc.).


> 2) Singletons tend to make refactoring a tad difficult, because they
> dramatically effect how navigation is done to the singleton. People
> rarely use wrapper methods, so it's all short-circuited directly to a
> static "getInstance()" method. So, if you have to refactor so that
> access is contextual, it tends to be a significant pain.


I think there are two issues here, which are often lumped together but 
need to be separated sometimes:

1). Sometimes it's nice to have a type that can only have one instance.
2). Sometimes it's nice to access resources in every context, i.e., to 
have context-free objects.

Traditionally, singletons often have both properties. For logging, it 
makes sense (everyone should be able to log); for keyboard access, well, 
it doesn't seem to make a lot of sense.

When it comes to controlling access, I've messed around with inheriting 
access; it's good when you want decentralized access control. When you 
want centralized access control, perhaps the simplest way is something 
like this:

class KeyboardAccessor : private SingletonHolder< Keyboard > {

friend class InputReader;
friend class EventManager;

};


This can be more sophisticated, to guard against the usual band of 
pitfalls, but I like that it uses simple language constructs: access is 
private, unless you're listed as a friend.


> So, one of the central tenants of log4cpp is that you have this global
> configuration and namespace which governs all the logging in a given
> process (so it's "one-per process"). There are neat little advantages to
> this, such as being able to turn on logging in a log4cpp-enabled DLL
> without having to compile it from source. However, as always, there are
> cases where this is actually not the desired effect. A simple example
> would be for something like an application server, where you might have
> multiple instances deployed within a given process, and you may want to
> have different logging configurations for each instance. Maybe you want
> to avoid extreme lock contention by having multiple logging sinks. You
> can try to hack around this using instance-based category names, but of
> course this will all fall apart if you are against using these 3rd party
> DLL's. Correcting this problem is non-trivial as much of log4cpp assumes
> the root category is a singleton.
> 
> If instead, getInstance() took a reference to the root category, and the
> system allowed for multiple roots, it'd be much more natural.


Well, log4cpp is not the most flexible and/or robust system in the world. 
Great for debugging race conditions, lousy for making your bounds 
checker-type utility shut up.



Jon
-- 
Jon Stewart
stew1@xxxxxxxxxxx
_______________________________________________
alacpp mailing list
alacpp@xxxxxxxxxxx
http://lists.ellipsis.cx/mailman/listinfo/alacpp