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