This is the mail archive of the
gcc@gcc.gnu.org
mailing list for the GCC project.
Re: Re: Re: Adding a new thread model to GCC
- From: "lh_mouse"<lh_mouse at 126 dot com>
- To: "Jonathan Wakely"<jwakely dot gcc at gmail dot com>
- Cc: "gcc"<gcc at gcc dot gnu dot org>, "mingw-w64-public"<mingw-w64-public at lists dot sourceforge dot net>
- Date: Wed, 20 Apr 2016 15:16:40 +0800
- Subject: Re: Re: Re: Adding a new thread model to GCC
- Authentication-results: sourceware.org; auth=none
- References: <2f3897eb dot bbc0e dot 1540ee9aa0b dot Coremail dot lh_mouse at 126 dot com> <CAH6eHdQ2b_NLLC6Hyq=tKgXhgAEhTdV1d2+sv6enHN7wG4JESQ at mail dot gmail dot com> <3eafd9c2 dot ce5a2 dot 154252730a4 dot Coremail dot lh_mouse at 126 dot com> <CAH6eHdQhDSwSt91xSi_yGSrsownGCErTP5H=3w1NrjXkr9T98Q at mail dot gmail dot com> <3d4feb73 dot d4007 dot 15428a9a070 dot Coremail dot lh_mouse at 126 dot com><CAH6eHdTz9HBJEgJqSse9QDJqs5KpUpVWi8FXScSVCL4-=kh9mg at mail dot gmail dot com>
One more question about block-scoped static objects:
>From compiled assembly I have learned that GCC uses a 64-bit integer guard to ensure once-initialization of static objects with block scopes.
Code in gcc/libstdc++-v3/libsupc++/guard.cc uses a global mutex to protect multiple threads from racing, which, as described in that file, could potentially cause a deadlock that can be avoided if a condition variable is used.
This, however, is unnecessary with mcfgthread. The mcfgthread library uses the once_flag itself as both the mutex and condition variable, eliminating the need of a global mutex and condition variable.
Code using mcfgthread might look like this:
[code]
class foo { ... };
static ::_MCFCRT_OnceFlag flag;
static alignas(foo) char obj[sizeof(foo)];
foo *get_obj(){
const auto construct_obj = []{ ::new(static_cast<void *>(obj)) foo(); };
const auto destruct_obj = []{ reinterpret_cast<foo *>(obj)->~foo(); };
// Lock the once flag as if it were a mutex.
const auto result = ::_MCFCRT_WaitForOnceFlagForever(&flag);
// This never times out, so result can be either _MCFCRT_kOnceResultInitial or _MCFCRT_kOnceResultFinished.
if(result == ::_MCFCRT_kOnceResultInitial){
try {
// Construct the object in-place.
construct_obj();
if(std::atexit(&destruct_obj) != 0){
// Assume we have run out of memory.
destruct_obj();
throw std::bad_alloc();
}
} catch(...){
// Unlock the once flag, allowing other threads to retry the initialization.
// This works like pthread_cond_signal().
::_MCFCRT_SignalOnceFlagAsAborted(&flag);
throw;
}
// We are done here. Unlock the once flag and other threads will not be blocked any more.
// This works like pthread_cond_broadcast().
_MCFCRT_SignalOnceFlagAsFinished(&flag);
}
return reinterpret_cast<foo *>(obj);
}
[/code]
Now here is my question:
That '__cxxabiv1::__guard' thing seems built-in of GCC. Does it have anything to do with code generation? And where is it involved?
------------------
Best regards,
lh_mouse
2016-04-20