| 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