Brian Cole wrote:
> I know that static initialization is not considered threadsafe from
> previous posts on this list. However, if a function static is POD
> being initialized by a function call then the value should always be
> initialized correctly, even if a inconsequential race condition
> occurs. This assumes that POD assignments are atomic, what platforms
> is this not true on?
All I know of. For example,
struct foo {
int a,b;
};
static struct foo f = {1,2};
is a POD initialization, and if two threads run into this line of code,
it may happen that thread A initializes f.b while thread B is already
using f.b for something else, so no, this is definitely not safe. Even
if you return a copy of f from a function:
struct foo init_me(void)
{
static struct foo f = {1,2};
return f;
}
the compiler may simply test a (non-mutex) protected flag in the
function and initialize f on the first call. If a second thread runs
into the function, it is unclear whether f will be initialized a second
time, or might return with a only partially initialized f instead.
Similarly,
void bar(void)
{
static struct foo = bla();
}
might call bla() once or several times, and might leave a second thread
with a partially initialized "foo" because a first thread already set
the "is initialized" flag on entry before the value has been copied over
completely.
In short: Don't do that.
> For example:
>
> unsigned int Bar(); // assumed to be a thread safe function that
> returns the same value every time
> void Foo()
> {
> static unsigned int value = Bar();
> }
Here you are returning an "int", not only a POD. On some architectures,
"int"s can be accessed "atomically", probably under certain constraints
(i.e. alignment), but once again, this is not a construction that you
should depend on.
> Then even if Bar is invoked concurrently `value` will always be the
> same for the rest of the Foo function call. Is this true? Or am I
> playing with fire?
You're playing with fire, sorry. Use a mutex to protect the
initialization of "foo".
Some compilers, e.g. gcc, will automatically wrap the initialization
into a mutex if compiled with proper options (-pthread), but this is
nothing ANSI C ensures for you, but rather a compiler extension.
So long,
Thomas


|