double-checked locking for singleton pattern

  • Permalink
  • submit to reddit
  • Email
  • Follow


Hello

After reading the Meyers& Alexandrescu article "C++ and the Perils of
Double-Checked Locking"
(http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf) which
claims that there is no
way of implementing double-checked locking for C++ singletons, I
wonder if the following simple
solution might do the work:

class Singleton {
public:
   static Singleton* instance();
....
private:
  Singleton();
  static Singleton * pInstance;
};

Singleton::Singleton()
{
  ... // do necessary initialisation
  pInstance = this;
}

Singleton* Singleton::instance() {
  if (pInstance == 0) {
    Lock lock;
    if (pInstance == 0) {
        new Singleton();
    }
  }
  return pInstance;
}

The issue which was highlighted in the article is related to the fact
that the line which looks like
pInstance = new Singleton;
can not be used in the Singleton::instance() function since some
compilers may generate code which would assign a value to the
pInstance variable right after allocating memory and BEFORE the
Singleton constructor is executed. It seems that a simple modification
shown above can overcome this problem. Am I wrong? Can someone comment
on that please.

Cheers,
Sergei

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kse13e 5/14/2008 2:12:42 PM

See related articles to this posting


<kse13e@yandex.ru> wrote in message
news:83b09fe9-210c-43eb-9030-ccd6096128ac@m36g2000hse.googlegroups.com...
> Hello
>
> After reading the Meyers& Alexandrescu article "C++ and the Perils of
> Double-Checked Locking"
> (http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf) which
> claims that there is no
> way of implementing double-checked locking for C++ singletons, I
> wonder if the following simple
> solution might do the work:

Its not going to work; there is a race-condition.

[...]

> The issue which was highlighted in the article is related to the fact
> that the line which looks like
> pInstance = new Singleton;
> can not be used in the Singleton::instance() function since some
> compilers may generate code which would assign a value to the
> pInstance variable right after allocating memory and BEFORE the
> Singleton constructor is executed. It seems that a simple modification
> shown above can overcome this problem. Am I wrong? Can someone comment
> on that please.

The problem is that your missing a memory barrier after you load from, 
and
before you store to the instance pointer. Here is sketch of 
high-performance
DCL algorithm that has all the correct barriers in place:
________________________________________________________________
template<typename T>
static T& once() {
  static T* g_this = NULL;
  static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
1:T* l_this = ATOMIC_LOADPTR_MBDEPENDS(&g_this);
  if (! l_this) {
    pthread_mutex_lock(&g_lock);
    if (! (l_this = g_lock)) {
      try {
2:      l_this = ATOMIC_STOREPTR_MBRELEASE(&g_this, new T);
      } catch (...) {
        pthread_mutex_unlock(&g_lock);
        throw;
      }
    }
    pthread_mutex_unlock(&g_lock);
  }
  return *l_this;
}
________________________________________________________________





Line 1 atomically load the shared pointer using trailing data-dependant
load-acquire memory barrier. Line 2 atomically stores to the shared 
pointer
using preceding store-release memory barrier:
________________________________________________________________
void* ATOMIC_LOADPTR_MBDEPENDS(void** p) {
  void* v;
  atomic {
    v = *p;
    MEMBAR #LoadStore | #LoadDepends;
  }
  return v;
}


void* ATOMIC_STOREPTR_MBRELEASE(void** p, void* v) {
  atomic {
    MEMBAR #LoadStore | #StoreStore;
    *p = v;
  }
  return v;
}
________________________________________________________________



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Chris 5/14/2008 5:25:53 PM

On May 14, 5:12 pm, kse...@yandex.ru wrote:
> Hello
>
> After reading the Meyers& Alexandrescu article "C++ and the Perils of
> Double-Checked Locking"
> (http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf) which
> claims that there is no
> way of implementing double-checked locking for C++ singletons, I
> wonder if the following simple
> solution might do the work:
>
....
>
> The issue which was highlighted in the article is related to the fact
> that the line which looks like
> pInstance = new Singleton;
> can not be used in the Singleton::instance() function since some
> compilers may generate code which would assign a value to the
> pInstance variable right after allocating memory and BEFORE the
> Singleton constructor is executed. It seems that a simple modification
> shown above can overcome this problem. Am I wrong? Can someone comment
> on that please.

The key quote from that paper:

"... people who do nothing but think about this kind of thing all day
long,
day after day, year after year. Unless you write optimizing compilers
yourself,
they are _way_ ahead of you."

Sorry, couldn't resist :)

--
  Nikolai



-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply nickf3 5/14/2008 11:05:07 PM

On 14 Maj, 23:12, kse...@yandex.ru wrote:
> Singleton::Singleton()
> {
>   ... // do necessary initialisation
>   pInstance = this;
>
> }
You do nothing to prevent compiler from changing the above code into:
Singleton::Singleton()
{
     pInstance = this;
     ... // do necessary initialisation
}
This could be due to some register usage optimalizations for example.

Cheers
Sfider

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Marcin 5/15/2008 3:04:50 PM

On 16 ???, 00:04, Marcin Swiderski <sfider.b...@gmail.com> wrote:
> On 14 Maj, 23:12, kse...@yandex.ru wrote:> Singleton::Singleton()
> > {
> >   ... // do necessary initialisation
> >   pInstance = this;
>
> > }
>
> You do nothing to prevent compiler from changing the above code into:
> Singleton::Singleton()
> {
>      pInstance = this;
>      ... // do necessary initialisation}
>


Thank you for the comment. I have realized that by reading the article
more attentively.
But what I still don't understand in it is the text on the page 11.
The authors claim that
the following code ensures proper initialisation order (the code is
already optimized):

Singleton* Singleton::instance()
{
   if (pInstance == 0) {
     Lock lock;
     if (pInstance == 0) {
         Singleton* volatile temp =
         static_cast<Singleton*>(operator new(sizeof(Singleton)));
         static_cast<volatile int&>(temp->x) = 5;
         pInstance = temp;
     }
   }
}

but then they are saying that "Unfortunately, this all does nothing
to address the first problem: C++'s abstract machine is single-
threaded,
and C++ compilers may choose to generate thread-unsafe code from
source
like the above, anyway."

I wonder how this may happen, i.e. what multi-threaded compiler might
be doing wrong about that code?

Cheers,
Sergei


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply kse13e 5/16/2008 4:31:53 PM

as commented in many of the posts and the afore mentioned paper from
Andrei Alexandrescu & Scott Meyers, the problem is the lack of
barriers. But as they comment in the very same paper:

"
At this point, one might reasonably wonder why Lock isn�t also
declared volatile. After all, it�s critical that the lock be
initialized before we try to write to pInstance or temp. Well, Lock
comes from a threading library, so we can assume it either dictates
enough restrictions in its specification or embeds enough magic in its
implementation to work without needing volatile. This is the case with
all threading libraries that we know of.
"

So, what would be the problem with the following implementation:

Singleton *pInstance;
Singleton* Singleton::instance()
{
    if (pInstance == 0) {
      Lock lock_1;
      if (pInstance == 0) {
          static Singleton* volatile temp = new Singleton();
          {
              Lock lock_2;
              pInstance = temp;
          }
      }
    }
}

if lock_2 works as a barrier against optimization, pInstance will
never be assigned before the object is correctly constructed ...

cheers,
- jan

ps.: i'm pretty sure there must be a problem, it wouldn't be that
simple, but i can't see how :)


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply pfeifer 5/29/2008 9:35:49 PM

On May 30, 6:35 am, pfei...@gmail.com wrote:
> as commented in many of the posts and the afore mentioned paper from
> Andrei Alexandrescu & Scott Meyers, the problem is the lack of
> barriers. But as they comment in the very same paper:
>
> "
> At this point, one might reasonably wonder why Lock isn't also
> declared volatile. After all, it's critical that the lock be
> initialized before we try to write to pInstance or temp. Well, Lock
> comes from a threading library, so we can assume it either dictates
> enough restrictions in its specification or embeds enough magic in its
> implementation to work without needing volatile. This is the case with
> all threading libraries that we know of.
> "
>
> So, what would be the problem with the following implementation:
>
> Singleton *pInstance;
> Singleton* Singleton::instance()
> {
>     if (pInstance == 0) {
>       Lock lock_1;
>       if (pInstance == 0) {
>           static Singleton* volatile temp = new Singleton();
>           {
>               Lock lock_2;
>               pInstance = temp;
>           }
>       }
>     }
>
> }
>
> if lock_2 works as a barrier against optimization, pInstance will
> never be assigned before the object is correctly constructed ...
>

Whether you use a lock or a barrier for synchronization, you need to
use the same object on all threads that need to be synchronized. In
particular lock_2 (assuming that it is actually locking a mutex, which
is not apparent from your code) is synchronizing with nobody: only one
thread will ever acquire it, so it is useless.

Also, AFAIK, nothing in your code, assuming a relaxed memory model,
guarantees that, if pinstance is != 0, it will actually point to a
valid object (and, no, I'm not talking about the fact you didn't zero
initialize it).


--
Giovanni P. Deretta


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply gpderetta 5/30/2008 7:50:54 AM

On Fri, 30 May 2008 08:50:54 -0600, gpderetta wrote:
> Whether you use a lock or a barrier for synchronization, you need to use
> the same object on all threads that need to be synchronized. 

Sorry, that is true. I failed to detail that in my pseudo-code. Let me
retry it:

Singleton *pInstance = 0;
Mutex mtx1, mtx2;

Singleton* Singleton::instance()
{
   if (pInstance == 0) {
     Lock lock_1(mtx1);
     if (pInstance == 0) {
       static Singleton* volatile temp = new Singleton();
       {
         Lock lock_2(mtx2);
         pInstance = temp;
       }
     }
  }
}


> In
> particular lock_2 (assuming that it is actually locking a mutex, which
> is not apparent from your code) is synchronizing with nobody: only one
> thread will ever acquire it, so it is useless.

Indeed it is synchronizing with nobody. But is there anyway for the
compiler to know that ? How can it know that no other thread is going to
synchronize on mtx2 ?

Well ... but maybe i'm back to the assumption that i can beat the
compiler into not optimizing something, which as A.Alexandrescu&S.Meyers
tries to discourage us from.

Although i would be surprised if today's compiler would optimize out a
lock like above -- it has to understand about all other possible threads,
and mtx2 being global, understand at link time that it is being only
locked in one place -- that means the linker has to know about the
semantics of locking.


> Also, AFAIK, nothing in your code, assuming a relaxed memory model,
> guarantees that, if pinstance is != 0, it will actually point to a valid
> object (and, no, I'm not talking about the fact you didn't zero
> initialize it).

the idea is that lock_2(mtx2) works as a barrier: that is the compiler
cannot move the assignment "pInstance = temp" across that.

If that is true, pInstance will only be != 0 after the object it points
to is properly constructed.

Otherwise many other things would break: imagine if the compiler starts
moving assignments on a shared memory structured before it actually
acquires the lock !?

thx
- jan


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Jan 5/30/2008 11:27:40 AM

On May 30, 8:27 pm, Jan Pfeifer <pfei...@stanford.edu> wrote:
> On Fri, 30 May 2008 08:50:54 -0600, gpderetta wrote:
> > Whether you use a lock or a barrier for synchronization, you need to use
> > the same object on all threads that need to be synchronized.
>
> Sorry, that is true. I failed to detail that in my pseudo-code. Let me
> retry it:
>
> Singleton *pInstance = 0;
> Mutex mtx1, mtx2;
>
> Singleton* Singleton::instance()
> {
>    if (pInstance == 0) {
>      Lock lock_1(mtx1);
>      if (pInstance == 0) {
>        static Singleton* volatile temp = new Singleton();
>        {
>          Lock lock_2(mtx2);
>          pInstance = temp;
>        }
>      }
>   }
>
> }
> > In
> > particular lock_2 (assuming that it is actually locking a mutex, which
> > is not apparent from your code) is synchronizing with nobody: only one
> > thread will ever acquire it, so it is useless.
>
> Indeed it is synchronizing with nobody. But is there anyway for the
> compiler to know that ? How can it know that no other thread is going to
> synchronize on mtx2 ?

Whole program analysis?

>
> Well ... but maybe i'm back to the assumption that i can beat the
> compiler into not optimizing something, which as A.Alexandrescu&S.Meyers
> tries to discourage us from.
>
> Although i would be surprised if today's compiler would optimize out a
> lock like above

compilers have surprised me many times.

> -- it has to understand about all other possible threads,
> and mtx2 being global, understand at link time that it is being only
> locked in one place -- that means the linker has to know about the
> semantics of locking.

If the linker can do link time optimizations, it certainly must. And
probably many do. For example I know for sure that there are Java
compilers that can remove useless locks. I wouldn't be surprised if C+
+ compilers did the same.

>
> > Also, AFAIK, nothing in your code, assuming a relaxed memory model,
> > guarantees that, if pinstance is != 0, it will actually point to a valid
> > object (and, no, I'm not talking about the fact you didn't zero
> > initialize it).
>
> the idea is that lock_2(mtx2) works as a barrier: that is the compiler
> cannot move the assignment "pInstance = temp" across that.
>
> If that is true, pInstance will only be != 0 after the object it points
> to is properly constructed.
>

This might fool some compilers which do not do whole program
compilation; It certainly won't fool the cpu, which is free to load
the pointed-to value before loading the pointer (yes, some cpus are
actually capable of doing that). I.e. you have to prevent reordering
(by the compiler or cpu), not only at the store, but also at the load.

> Otherwise many other things would break: imagine if the compiler starts
> moving assignments on a shared memory structured before it actually
> acquires the lock !?
>

As long as you use locks correctly AND your compiler understands them,
nothing will break.

--
Giovanni P. Deretta

-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply gpderetta 5/30/2008 3:11:07 PM

"Jan Pfeifer" <pfeifer@stanford.edu> wrote in message
news:g1p6n2$nl6$1@news.stanford.edu...
> On Fri, 30 May 2008 08:50:54 -0600, gpderetta wrote:
>> Whether you use a lock or a barrier for synchronization, you need to use
>> the same object on all threads that need to be synchronized.
>
> Sorry, that is true. I failed to detail that in my pseudo-code. Let me
> retry it:
>
> Singleton *pInstance = 0;
> Mutex mtx1, mtx2;
>
> Singleton* Singleton::instance()
> {
>   if (pInstance == 0) {
>     Lock lock_1(mtx1);
>     if (pInstance == 0) {
>       static Singleton* volatile temp = new Singleton();
>       {
>         Lock lock_2(mtx2);
>         pInstance = temp;
>       }
>     }
>  }
> }
[...]

Its not guaranteed to work because there are mutex implementations out there
which do not use a memory barrier after every lock procedure; here is an
example:

http://groups.google.com/group/comp.programming.threads/browse_frm/thread/22b2736484af3ca6

Therefore, you would need to store into `pInstance' _after_ mtx2 has been
acquired and released. Here is a sketch:
______________________________________________________________
#include <pthread.h>

class mutex_guard {
  pthread_mutex_t* const m_mtx;
public:
  mutex_guard(pthread_mutex_t* const mtx) : m_mtx(mtx) {
    pthread_mutex_lock(m_mtx);
  }
  ~mutex_guard() throw() {
    pthread_mutex_unlock(m_mtx);
  }
};

template<typename T>
static T& once() {
  static T* volatile g_this = NULL;
  static pthread_mutex_t g_main_mtx = PTHREAD_MUTEX_INITIALIZER;
  static pthread_mutex_t g_mem_mtx = PTHREAD_MUTEX_INITIALIZER;
  T* l_this = g_this;
  if (! l_this) {
    mutex_guard const main_lock(&g_main_mtx);
    if (! l_this) {
      l_this = new T;
      {
        mutex_guard const mem_lock(&g_mem_mtx);
      }
      g_this = l_this;
    }
  }
  return *l_this;
}

______________________________________________________________


However, its still not guaranteed to work because it has undefined behavior
according to the PThread Standard. Although, it will most certainly work in
practice on some existing platforms if the compiler does not optimize the
`g_mem_mtx' lock/unlock sequence away...


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Chris 5/30/2008 3:14:26 PM

"Chris Thomasson" <cristom@comcast.net> wrote in message
news:jeudncfHdoRq9d3VnZ2dnUVZ_vqdnZ2d@comcast.com...
> "Jan Pfeifer" <pfeifer@stanford.edu> wrote in message
> news:g1p6n2$nl6$1@news.stanford.edu...
>> On Fri, 30 May 2008 08:50:54 -0600, gpderetta wrote:
>>> Whether you use a lock or a barrier for synchronization, you need to use
>>> the same object on all threads that need to be synchronized.
>>
>> Sorry, that is true. I failed to detail that in my pseudo-code. Let me
>> retry it:
>>
[...]
>
> Its not guaranteed to work because there are mutex implementations out 
> there
> which do not use a memory barrier after every lock procedure; here is an
> example:
>
> http://groups.google.com/group/comp.programming.threads/browse_frm/thread/22b2736484af3ca6
>
> Therefore, you would need to store into `pInstance' _after_ mtx2 has been
> acquired and released. Here is a sketch:
> ______________________________________________________________
[...]
> ______________________________________________________________
>
>
> However, its still not guaranteed to work because it has undefined 
> behavior
> according to the PThread Standard. Although, it will most certainly work 
> in
> practice on some existing platforms if the compiler does not optimize the
> `g_mem_mtx' lock/unlock sequence away...

One platform where this is guaranteed NOT to work would be DEC Alpha. That
architecture does not have implicit data-dependant load barrier. This will
bust the initial load of `pInstance'. The Alpha requires a memory barrier
after the load...


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Chris 5/30/2008 10:20:33 PM

"Chris Thomasson" <cristom@comcast.net> wrote in message
news:jeudncfHdoRq9d3VnZ2dnUVZ_vqdnZ2d@comcast.com...
[...]
> ______________________________________________________________
[...]
> template<typename T>
> static T& once() {
>  static T* volatile g_this = NULL;
>  static pthread_mutex_t g_main_mtx = PTHREAD_MUTEX_INITIALIZER;
>  static pthread_mutex_t g_mem_mtx = PTHREAD_MUTEX_INITIALIZER;
>  T* l_this = g_this;
>  if (! l_this) {
>    mutex_guard const main_lock(&g_main_mtx);
>    if (! l_this) {
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
ARGH!

      if (! (l_this = g_this)) {


of course! Sorry for that non-sense.

[...]


-- 
      [ See http://www.gotw.ca/resources/clcm.htm for info about ]
      [ comp.lang.c++.moderated.    First time posters: Do this! ]

0
Reply Chris 6/1/2008 2:01:12 AM
comp.lang.c++.moderated 10643 articles. 9 followers. Post

11 Replies
273 Views

Similar Articles

[PageSpeed] 54


  • Permalink
  • submit to reddit
  • Email
  • Follow


Reply:

Similar Artilces:

Double-Checked Locking pattern issue
Hello gurus, For the wellknown Double-Checked Locking pattern, http://www.ddj.com/184405726?pgno=1 Step 1: Allocate memory to hold a Singleton object. Step 2: Construct a Singleton object in the allocated memory. Step 3: Make pInstance point to the allocated memory. After reading for a couple of times, I still do not understand why some compiler will exchange step 2 and step 3 code? If there are any exception in step 2, the swap code will make pInstance point to an invalid memory address. Any ideas why compiler do the swap? [Code] Singleton* Singleton::instance() { if (pInstance == 0) {...

Double checked locking pattern article on aristeia
There is something in this article that puzzles me http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf The article says the following code may not work correctly in a multi-threaded environment for two reasons. The code has volatile all over the place to prevent the compiler from re-ordering code. The idea is to avoid acquiring the (expensive) Lock every time you need to access the singleton. class Singleton { public: static volatile Singleton* volatile instance(); //... private: // static volatile Singleton* volatile pInstance; }; // from the implemen...

implementation of "Double-Checked Locking" Pattern in C++
Hi All, The Double-Checked Locking Pattern is a common approach to efficient lazy initialization. Unfortunately, it's not reliable in C++ in threaded systems, it can fail for different reasons in uniprocessor and multiprocessor environments, and there's no portable way to make it reliable. Is there any way for implementing the "Double Check Lock Pattern" 100% Thread Safe??? Sample C++ code example code that implements Double-Checked Locking: Singleton* Singleton::Instance() { if (0 == pInstance) { Guard lock(m_mutex); if (0 == pInstance) pInstance = new Singleton; } ...

Double checked locking
Hi, I have a question on the double checked locking. The classic implementation (shamelessly copied from Scott Meyers' and Andrei Alexandrescu's article) class Singleton { public: static Singleton* instance(); .... private: static Singleton* pInstance; }; Singleton* Singleton::instance() { if (pInstance == 0) { // 1st test Lock lock; if (pInstance == 0) { // 2nd test pInstance = new Singleton; } } return pInstance; } is unsafe as there is no guarantee that the assignment of pInstance is done after the constructor of Single...

performance of double checked locking
Hello The double checked locking idiom (thread safe singelton pattern) now works correct under the current memory model: public class MySingleton { private static volatile MySingleton instance; public static MySingleton getInstance() { if (instance == null) { synchronized (MySingleton.class) { if (instance == null) { instance = new MySingleton(); } } } return instance; } } Nevertheless the Java experts still discourage its use, claiming that there would be no signifcant perfor...

pthread_once and double checked locking
Hi, regarding: http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/lib/libc/port/threads/pthread.c#134 This pthread_once implementation here seems to be using double checked locking. I am told this is broken. I even mostly understand why. So why is the above using double checked locking? Or is it some variation that works? From all I understand on the topic, the only true and correct solution is a solution that involves hardware specific behaviour. Thanks for your response, Sohail u.int.32.t@gmail.com wrote: > Hi, > > regarding: > http://src.o...

double-checked locking in C
Hi, I would like to use the DCL idiom (double-checked locking) to guarantee the once and only once execution of an initialization code: bool initialized = false; pthread_mutex_t mutex; void function(void) { if (!initialized) { pthread_mutex_lock(&mutex); if (!initialized) { initialized = true; init_code(); } pthread_mutex_unlock(&mutex); } } I know that in Java there were problems with this idiom due to the memory operation reorderings and these have been apparently solved in Java 1.4. Is there any problem usi...

double-checked locking and weak ordering
Hi, I don't usually post to comp.arch, so I hope this is appropriate. I think this post is more appropriate here than comp.programming.threads. I wasn't able to find the comp.arch FAQ after searching a couple pages of results on google. I'm wondering if this double-checked locking pattern is right on say an Alpha or PA-RISC system with weak memory ordering. This code is used for thread-specific data. if (keyPtr->offset == 0) { Tcl_MutexLock(&tsdMaster.mutex); if (keyPtr->offset == 0) { /* * The Tcl_ThreadDataKey hasn'...

Double-checked locking: is this alternative OK?
SomeObject* instance() // flawed way { static SomeObject* instance = NULL; LockThing(); // locking even when not required if(instance == NULL) // instance may still be NULL when another thread checks instance = new SomeObject(); UnlockThing(); // oh dang, more unnecessary function calls after first pass return instance; } SomeObject* instance() // OK? { static bool been_there_done_that = LockThing(); static volatile instance = new SomeObject(); // no problemo (on X86 hardware) static bool been_there_done_that_B = UnlockThing(); return instance; //...

[ace-users] Double checked locking on multiprocessor
Can anyone confirm or deny that ACE's use of double-checked locking works in multi-CPU settings on Intel Linux machines? I would be extremely surprised if the answer is "no it doesn't work" but before I keep searching for another reason for the behavior I'm seeing, I want to double check that there isn't a known problem in this area. A. On Tuesday 16 November 2004 05:12, Andrew A. wrote: > Can anyone confirm or deny that ACE's use of double-checked locking works > in multi-CPU settings on Intel Linux machines? > > I would be extrem...

Solving Lazy Initialization and double checked locking problem
I have been thinking about the lazy initialization and double checked locking problem. This problem is explain in detail here http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html I am not fully convinced that this problem cannot be solved. I am going to propose a solution here. For the sake of discussion I will post my solution here. It is possible that the proposed solution does not work, feedback and comments are welcome. Here is the original problem. We need to lazy initialize a non static variable to an instance of a heavy object in a thread safe way. (It is very easy...

RE: [ace-users] Double checked locking on multiprocessor
Indeed. It's this type of reading that has me wondering :-) Most of the discussions regarding the failure cases of double checked locking involve cache consistency issues for NUMA architectures and JVM/CLRs. These issues can be resolved by using a memory barrier instruction following the first check and last assignment. What I don't know is whether ACE's use of a lock following the first check, and an unlock following the assignment, constitues the appropriate memory barriers on P3, P4 and P4 HT Intel hardware. By the way, the particularl document that struck fea...

Please disprove this Double-Checked Locking "fix"
Hi, Recently I've been reading up on "Double-Checked Locking" in C++ and how it's often implemented imperfectly. The Article "C++ and the Perils of Double-Checked Locking" by Scott Meyers and Andrei Alexandrescu ( http://www.aristeia.com/Papers/DDJ_Jul_Aug_2004_revised.pdf ) provides a good overview of how it's usually done and why it's often inadequate. I won't go into details here, but the article states how this code: Singleton* Singleton::instance() { if (pInstance == 0) { Lock lock; if (pInstance == 0) { pInstance = new Sin...

Shalloway and Trott's solution to double checked locking?
Shalloway and Trott, in their book Design Patterns Explained, 2nd edition, published what they claim to be a fix for the broken Double-Checked Locking Pattern. Would the following truly be a valid means of implementing a thread-safe singleton? --- Begin quote from Design Patterns Explained --- When the Double-Checked Locking pattern was converted from C++ to Java, it was soon discovered that it did not work for Java.[4] The reason is that the Java compiler, in its optimization efforts, may return the reference to an object from a constructor before the constructor is through instantiating th...

Double checked locking (yet another attempt to get around)
Hi all, I'm sure this has been discussed before, here is what I have: private static boolean propsLoaded = false; private static Object propsGuard = new Object(); private Properties props = null; . . . protected someMethod() { if (!propsLoaded) { synchronized(propsGuard) { if (props == null) { // Only get properties file if we have never done so props = getProperties_(PROPERTIES_FILE); } log("I have loaded the properties file."); } if (props != null) propsLoaded = true; } . . } This class is going to be used i...

[ace-users] Double-Checked Locking in HP-Unix Environment
Hi Prasad, > I'm facing some design/implementation issues while developing a > Multithreaded C++ application. I have two questions for you. > > 1) I went through your article on "Double-Checked Locking". I was > wondering whether I can implement this pattern in a > Multithreaded Application using C++( Compiler : HP ANSI C++ > (aCC) version A.03.13) in HP-UX 11 environment. (Is there any > issues related to Compiler Optimization/OS memory model) If you > already have any data regarding this, could you please let me &g...

Double check locking
Hi All, There is very well known 'fix' of double check locking (used particularly i= n singleton implementation) which uses release memory barrier on (before) t= he pointer assignment and acquire memory barrier on (after) pointer reading= .. Now, correct me if I am wrong (I may very well be), but there is no general= promise that causality is supported by any system, at least as for C++ me= mory model, the relation 'happens-before' is not guaranteed to be transitiv= e. This may mean that if Thread T1 constructs singleton X, Thread T2 'acquires= ' singl...

ctime double double check
Hi I am using ctime to convert the following string 1144412677847 .... Please could some one to double check if they get the same result as me (The Time is Sun Nov 02 09:11:51 2031). It seems incorrect and would like a second opion. #include <time.h> #include <stdio.h> int main () { unsigned long Timestamp; time_t CTime; Timestamp= (long)1144412677847 ; CTime=ctime(&Timestamp); printf ("The Time is %s", CTime); exit(0); } The Time is Sun Nov 02 09:11:51 2031 On Mar 8, 9:28 am, aisling.cro...@gmail.com wrote: > Hi > > I am using ctime to convert...

Singleton classes and Singleton pattern
I just happened upon singleton classes, and was wondering two things: 1) There's no difference between these two codes, right? Is there an advantage or disadvantage over either? Does Ruby put bar() into the same virtual class object for both? class Foo class << self def bar end end end class Foo def self.bar end end 2) A singleton class has nothing to do with the singleton design pattern, right? They only share the same name because there is only ever one of them. Hi -- On Wed, 11 Oct 2006, Wilhelm wrote: > I just happened upon singleton classes, and was...

where to find good patterns and sources of patterns (was Re: singletons)
"Jonathan Turkanis" <technews@kangaroologic.com> wrote: > "johny smith" <princetonharvard@charter.net> wrote: > >> Can someone point me to some good articles on how >> to create singleton objects and how to access >> operations within a singleton object. > > 1. Design Patterns, by Gamma et al, Ch. 3 -- classic > description of the pattern > 2. Modern C++ Design, Alexandrescu Ch. 6 -- thorough > discussion and ingenious implementation of C++ singletons > > Once you've absorbed these, you might want to look at >...

locking patterns
I am thinking about how to use locks efficiently. One example. Say I have some I/O threads and some computational threads a mutex and a queue. The I/O threads receive I/O, do some simple parsing and send result over to the computational thread pool for further processing. I was wondering if setting up the I/O threads like this would be beneficial: io_work_batch_queue g_queue; mutex g_mutex; cond g_cond; void io_thread() { for (;;) { io_work_batch workb; io_wait_for_data(workb); workb.simple_parsing(); while (! g_mutex.try...

How to check for locks
-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 Is there a way to get a list of sessions (threads) currently waiting on locks, and possibly even the holder of the lock? I'm using mysql 5.0.41 and InnoDB storage engine. Thanks. TIA -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.5 (GNU/Linux) Comment: Using GnuPG with PCLinuxOS - http://enigmail.mozdev.org iEYEARECAAYFAkfRw+8ACgkQzIf+rZpn0oRGGgCfSwuok6Nn1GP2FBBxZzWUojKl NmsAnjW2EAn1M+Wf23ZzVbWXUZwPicqH =5P/a -----END PGP SIGNATURE----- Chuck wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA1 > > Is there a way to get ...

THE SINGLETON PATTERN?
Hello everyone, I have been researching the Singleton Pattern. Since the singleton pattern uses a private constructor which in turn reduces extendability, if you make the Singleton Polymorphic what sort of problems/issues should be considered? Also, I see that a singleton needs to be set up with certain data such as file name, database URL etc. What issues are involved in this, and how would you do this? If someone knows about the Singleton pattern please reply. Thanks Alicia "Alicia Roberts" <alic2301@hotmail.com> wrote... > Hello everyone, I have been researc...

singleton pattern
Typical i write my singletons like this: protected static MyClass singleton; protected MyClass() { } public static MyClass getInstance() { if( singleton == null ) { singleton = new MyClass(); } return singleton; } However on more than once occasion I've come across this: protected static MyClass singleton = new MyClass(); protected MyClass() {} public static MyClass getInstance() { return singleton; } Now for some reason the seconds way bothers me. I am not sure why ? Is there something to this ? Or I am just being stupid ? joe "joe" <jpribele@bglgroup.com> writes: ...