Discussion:
Singletone - double check
(too old to reply)
Ofer Gaatone
2008-05-26 12:27:05 UTC
Permalink
Hi,
i'm using BCB 6 under Win2000. Trying to write a single in
multi-threaded environment i want to use double check.
this is my code:

if (pPrmt == NULL)
{
// lock
if (pPrmt == NULL)
pPrmt = new CPrmpt(pFileName);
// unlock
}

I don't know when and where should i create the semaphore that i will
use for lock and unlock ?

Any help, documents, example or link would be great

Thanks
Ofer
Chris Uzdavinis (TeamB)
2008-05-30 12:38:04 UTC
Permalink
Post by Ofer Gaatone
Hi,
i'm using BCB 6 under Win2000. Trying to write a single in
multi-threaded environment i want to use double check.
if (pPrmt == NULL)
{
// lock
if (pPrmt == NULL)
pPrmt = new CPrmpt(pFileName);
// unlock
}
I don't know when and where should i create the semaphore that i will
use for lock and unlock ?
Any help, documents, example or link would be great
It's a hard problem, especially since it's theoretically impossible to
solve. However, given limitations of computers and compilers, you can
usually find a way to get double checked locking to work.

When to initialize the mutex is an interesting problem, because what
if two threads try to simultaneously initialize the mutex? Then you
end up with two, and serious problems. One solution to help with this
problem is solvable by programming convention, but not with any help
of the language: never start any threads in constructors of objects
that are "global variables", static members of objects, or static
local variables to functions that may get called before main.

In short, if you start threads before main, your task of correctness
becomes nearly impossible. If you designate "before main" as a
single-thread section of your application, it's then safe to construct
locks in the initialization section of your program, such as declaring
one in the anonymous namespace of your cpp file that requires it.
--
Chris (TeamB);
Jason Cipriani
2008-05-30 13:24:03 UTC
Permalink
Post by Ofer Gaatone
if (pPrmt == NULL)
{
// lock
if (pPrmt == NULL)
pPrmt = new CPrmpt(pFileName);
// unlock
}
I don't know when and where should i create the semaphore that i will use
for lock and unlock ?
Any help, documents, example or link would be great
You want to ask this question on comp.programming.threads. You can access it
with your favorite newsreader or via Google groups:

http://groups.google.com/group/comp.programming.threads/topics

You will most likely get some very solid answers and possibly alternative
suggestions there.

Jason
Remy Lebeau (TeamB)
2008-05-30 16:33:17 UTC
Permalink
Post by Ofer Gaatone
if (pPrmt == NULL)
{
// lock
if (pPrmt == NULL)
pPrmt = new CPrmpt(pFileName);
// unlock
}
I just yesterday saw a third-party piece of code that uses
InterlockedCompareExchangePointer() for that kind of logic without using
extra locks, ie:

if( pPrmt == NULL )
{
CPrmpt *lPrmt = new CPrmpt(pFileName);
if( InterlockedCompareExchangePointer((PVOID*)&pPrmt, lPrmt, NULL)
!= NULL )
delete lPrmt;
}
Post by Ofer Gaatone
I don't know when and where should i create the semaphore
that i will use for lock and unlock ?
Well, where and how is pPrmt being used to begin with?



Gambit
Alan Bellingham
2008-05-31 09:01:15 UTC
Permalink
Post by Remy Lebeau (TeamB)
I just yesterday saw a third-party piece of code that uses
InterlockedCompareExchangePointer() for that kind of logic without using
if( pPrmt == NULL )
{
CPrmpt *lPrmt = new CPrmpt(pFileName);
if( InterlockedCompareExchangePointer((PVOID*)&pPrmt, lPrmt, NULL)
!= NULL )
delete lPrmt;
}
Cute.

I like the way the code has remembered to delete lPrmt in case another
thread allocated it between initial check and creation of the new one.

Alan Bellingham
--
Team Browns
ACCU Conference 2009: to be announced
Chris Uzdavinis (TeamB)
2008-06-02 18:10:19 UTC
Permalink
Post by Alan Bellingham
Cute.
I like the way the code has remembered to delete lPrmt in case another
thread allocated it between initial check and creation of the new one.
We had a similer issue with CORBA re-entrancy. While handling the
first call, a second call came in, and attempted to create the same
object that the first call (which it interrupted) was creating.

To ensure that both calls return the same object, before sticking the
new one into a hash-table, it had to lookup the value again and see if
one's already there. If it is, then it destroyed the one it just
created, and returns the original object (which presumably has already
been returned to a caller, so that's the one that's already in use.)

Coincidently, I'm refactoring that code today. :)
--
Chris (TeamB);
Loading...