$include_dir="/home/hyper-archives/boost/include"; include("$include_dir/msg-header.inc") ?>
From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2002-10-18 11:50:00
David Abrahams wrote:
> 
> tss.html - ....
Speaking and/or thinking of TSD and TLS you might want to consider 
the following: (don't miss ISO/EIC "edits" below)
Subject: Re: local statics and TLS objects 
Date: 2002-10-11 05:37:42 PST 
Alexander Terekhov wrote:
>
Well, "thread-private" was a bit confusing. I should have used something 
like "thread-local". Also... Momchil, see yet another "fixed" DCL below.
> < was: Re: volatile -- what does it mean in relation to member functions?
>   comp.lang.c++.moderated >
> 
> James Kanze wrote:
> [...]
> > > > Posix says nothing about C++.  A C++ compiler can do what it wants,
> > > > and not affect Posix compliance.  Still, I can't imagine a C++
> > > > compiler not extending the guarantees of C to cover its operations.
> > > > (It does mean, however, that a fair number of C++ compilers do not
> > > > generate thread safe code, particularly when it comes to
> > > > initializing local statics. [...]
> > > Been there done that. That static local initialization doesn't work in
> > > a lot of compilers is very unfortunate. Since the C++ standard clearly
> > > says that it should be initialized on the first call there's really no
> > > excuse. It doesn't say under which circumstances so this means this
> > > should hold under *any* circumstances and if your compiler even has a
> > > switch to notify it about multithreaded code...
> >
> > I tend to agree with you here. ....
> 
> I disagree. And, BTW, I'd be quite happy to be able to write
> something like:
> 
> ThreadLocalLazySingleton&
>   ThreadLocalLazySingleton::get() // static
> {
>    // Kinda "static" but might throw std::bad_alloc even
>    // if used with throw() [throw nothing] constructor[1].
>    static(thread_private) ThreadLocalLazySingleton thing(/**/);
>    return thing;
> }
> 
> and
> 
> GlobalLazyImmutableSingleton const&
>   GlobalLazyImmutableSingleton::get() // static
> {
>    // Thread shared/safe version of "classic" local static. See
>    // the link below (i.e. it's synchronized using __cxa__guards).
>    static(thread_shared) const GlobalLazyImmutableSingleton thing(/**/);
>    return thing;
> }
> 
> leaving
> 
> ThreadsUnawareGlobalLazySingleton&
>   ThreadsUnawareGlobalLazySingleton::get() // static
> {
>    // This thing is "single threaded" -- NOT meant to use
>    // http://www.codesourcery.com/cxx-abi/abi.html#once-ctor
>    // "sync-guards"/synchronization-by-default
>    static ThreadsUnawareGlobalLazySingleton thing(/**/);
>    return thing;
> }
> 
> alone (with respect to threading)... for things like:
> 
> // Module
> 
> static ReadWriteLock s_lock;
> 
> LazySingletonWithReadWriteAccess*
>   LazySingletonWithReadWriteAccess::s_inst = 0; // set in c-tor
> 
> auto_unlock_ptr< LazySingletonWithReadWriteAccess >
>   LazySingletonWithReadWriteAccess::getForWrite() // static
> {
>   ReadWriteLock::WriteGuard guard( s_lock );
>   static LazySingletonWithReadWriteAccess thing(/**/);
>   return auto_unlock_ptr<
>            LazySingletonWithReadWriteAccess >(&thing,guard);
> }
> 
> auto_unlock_ptr< const LazySingletonWithReadWriteAccess >
>   LazySingletonWithReadWriteAccess::getForRead() // static
> {
>   {
>     ReadWriteLock::ReadGuard guard( s_lock );
>     if ( s_inst )
>       return auto_unlock_ptr<
>          const LazySingletonWithReadWriteAccess >(s_inst,guard);
>   } return getForWrite().degradeToReadOnlyAccess();
> }
> 
> Or am I just missing and/or misunderstanding something?
> 
> How is this currently done by the existing C++ implementations
> that already provide TLS (supporting constructors/destructors)?
> 
> regards,
> alexander.
> 
> [1] So, basically:
> 
> extern void operation( Something& );
> extern(thread_private) Something thing = blah_blah;
> 
> /* ... */
> 
> operation( thing );
> 
> would actually mean something along the lines of:
> 
> extern void operation( Something& );
> extern Something& __thing() // throw( std::bad_alloc, ... )
> {
>   static(thread_private) Something thing = blah_blah;
>   return thing;
> }
> 
> operation( __thing() );
< was: Re: Talking about volatile and threads synchronization... >
Momchil Velikov wrote:
[...]
> So, the DCL case will looke like this, right ?
> 
> void foo ()
> {
>   static int initialized;
>   int i;
> 
>    i = initialized;
> 
>    /* Read memory barrier, so the above read of ``initialized''
>       is issued before reads of memory, initialized by ``do_stuff''.
>       We may not need this on some architectures. Which ones ? */
>    rmb ();
>    if (i == 0)
>    {
>       lock ();
>       if (initialized == 0)
>       {
>          do_stuff ();
> 
>          /* Write memory barrier - prevent CPU from reordering
>             writes across this point. Necessary (but not
>             necessarily sufficient) to ensure the reader sees
>             the new values written in ``do_stuff''
>             whenever it sees ``initialized'' being nonzero.  */
>          wmb ();
>          initialized = 1;
>       }
>       unlock ();
>    }
> 
>   do_more_stuff ();
> }
Nah, given the following {rather intereseting(*)} 
"ISO/EIC xxxx:xxxx edits": ;-)
http://gcc.gnu.org/onlinedocs/gcc/C99-Thread-Local-Edits.html#C99%20Thread-Local%20Edits
(ISO/IEC 9899:1999 Edits for Thread-Local Storage)
http://gcc.gnu.org/onlinedocs/gcc/C--98-Thread-Local-Edits.html#C++98%20Thread-Local%20Edits
(ISO/IEC 14882:1998 Edits for Thread-Local Storage)
So, the DCL case will look like this:
void foo ()
{
  static int initializedGlobal;
  static __thread int initializedThreadLocal;
  if (initializedThreadLocal == 0)
  {
      lock ();
      if (initializedGlobal == 0)
      {
         do_stuff ();
         
         initializedGlobal = 1;
      }
      unlock ();
      initializedThreadLocal = 1;
   }
 
  do_more_stuff ();
}
regards,
alexander.
(*) Does DEC's/Compaq's/NewHP's TLS have the same "semantics" with 
    respect to non-lazy/eager "static" TLS inits -- NOT supporting 
    dynamic initialization/C++ c-tors? What about dlopen(), then?