Re: What is the problem with writing singleton in multithreaded enviroment
James Kanze wrote:
Timo Geusch wrote:
James Kanze wrote:
[...]
Double checked locking doesn't really apply in your case anyway
but would normally look like this C++-like pseudo code:
foo* bar::get_foo_instance()
{
if (!foo_instance) {
lock.aquire();
if (!foo_instance) [
foo_instance = new foo;
}
lock.release();
}
}
Except, of course, that this code doesn't work.
That's why it's called pseudo code :).
I wasn't sure whether you were suggesting it, or simply saying
that this is what is generally meant by DCL.
I was trying to give a very simple example of DCL as the OP sounded
like he hadn't come across this idiom before.
I suspected the
latter, but I do feel it better to indicate to the original
poster that DCL doesn't work, at least not without some special
assembler (or a compiler extension, but I don't know off hand of
any compiler which offers one).
Well, I'm one of these wussy people who actually do read compiler
documentation and I haven't come across it, either. That said, I use
pretty much the same toolset as you (g++/VC++/SUN CC) so it may well be
that one of the more exotic compilers actually offers a compiler
extension for this.
Note that both this and the original version with the local
static work fine IF you can guarantee that the first call to the
function (which triggers construction) occurs before
multithreading starts. (Note, however, that this guarantee is
something I have established pragmatically, based on what I know
about how compilers handle local statics. The standard is, of
course, silent about it, and I've yet to see a compiler which
actually gives an explicit guarantee.) I often do something
like:
foo* foo_instance = bar::get_foo_instance() ;
for example, to ensure that the function is called once during
the initialization of static objects---on every compiler I know
of, this occurs before entering main, and I never start
threading until after entering main.
That's a technique I tend to use for objects shared between threads as
well after empirically determining the lack of compiler guarantees
(otherwise known as getting it wrong).
Another solution that I've occasionally used is based on the
fact that if the singleton object is not const, client code will
probably need a lock anyway to access it. So I merge the two,
acquiring the lock before the first test of the pointer, and
returning a boost::shared_ptr to the object, with a "destructor"
which frees the lock (rather that deleting the object).
Now *that* is a neat technique. I'll try to keep that in mind!
--
The lone C++ coder's blog: http://www.bsdninjas.co.uk/codeblog/
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]