Discussion:
pthread_mutex_init in global c++ ctor?
(too old to reply)
roland
2004-12-17 12:32:33 UTC
Permalink
Is it allowable to call e.g.
pthread_mutex_init

before main(), as may happen when used
from a global C++ constructor?

Is this undefined/implementation dependant behaviour?


Thanks,
roland
Giancarlo Niccolai
2004-12-17 12:41:07 UTC
Permalink
Post by roland
Is it allowable to call e.g.
pthread_mutex_init
before main(), as may happen when used
from a global C++ constructor?
Is this undefined/implementation dependant behaviour?
Yes, pthread_* objects may be initialized before main.

However, it is a programming practice to be avoided. Suppose that one day
you have to use your static constructed object from another static
constructed one. In that case the pthread_mutex_init() may get called or
not (50% chance). So, for so delicate things, it is more advisable to:
1) construct explicitly objects in main.
2) construct them statically, but issue a failure exception if their init()
method (from main or from any safe point) has not been called.
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.

Bests,
Giancarlo Niccolai.
roland
2004-12-17 13:16:27 UTC
Permalink
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
do you mean:
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;

...

main()
{
...
pthread_mutex_lock(&global_mutex);
...
}

which causes the mutex to be initialized on first use?
(at least in ptw32 implementation)

Roland
Giancarlo Niccolai
2004-12-17 23:10:04 UTC
Permalink
Post by roland
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
No, I mean:

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13

But I suggest you to read the whole chapter carefully.

Gian.
Giancarlo Niccolai
2004-12-17 23:19:05 UTC
Permalink
Post by Giancarlo Niccolai
Post by roland
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13
But I suggest you to read the whole chapter carefully.
Gian.
Also, maybe you should start here instead of the previous link:

http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12

Gian
Tom Widmer
2004-12-20 13:51:25 UTC
Permalink
Post by Giancarlo Niccolai
Post by roland
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13
But I suggest you to read the whole chapter carefully.
But dynamically initialized static local variables are not threadsafe.
If two threads call the function at the same time (and it hasn't been
called before), there is a race condition over initialization of the
static variable (a mutex in this case). It may end up being initialized
twice, with the two threads using different copies!

The threadsafe way to initialize a mutex is via:
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
You can have it as a static variable in a function, but there isn't much
point, since it is initialized at compile time (static rather than
dynamic initialization) in such a way that the first time it is locked,
any runtime initialization that needs to be done is done in a thread
safe way.

Tom
roland
2004-12-20 15:21:53 UTC
Permalink
Post by Tom Widmer
Post by Giancarlo Niccolai
Post by roland
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13
But I suggest you to read the whole chapter carefully.
But dynamically initialized static local variables are not threadsafe.
If two threads call the function at the same time (and it hasn't been
called before), there is a race condition over initialization of the
static variable (a mutex in this case). It may end up being initialized
twice, with the two threads using different copies!
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
You can have it as a static variable in a function, but there isn't much
point, since it is initialized at compile time (static rather than
dynamic initialization) in such a way that the first time it is locked,
any runtime initialization that needs to be done is done in a thread
safe way.
That means
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
is the correct answer. However a question remains then:
Who is responsible of deallocation then?
I hope it is in charge of the implementation of the pthreads
library to release the mutex after last use. Am I correct
with this assumption?
I.e. If I wrap things up so that
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
takes place in my C++ ctor, I have to leave the dtor empty.

Hmm, this is bad, because it would prevent dynamically creating
C++ wrapped mutexes or putting them on the stack. I am afraid
I would end with lot of used memory then which only again gets
destroyed on program termination.

Any thoughts?

Roland
Alexander Terekhov
2004-12-20 15:44:29 UTC
Permalink
roland wrote:
[...]
Post by roland
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
Who is responsible of deallocation then?
Not sure what you mean. You can call pthread_mutex_destroy() on
a statically allocated pthread_mutex_t object initialized by
PTHREAD_MUTEX_INITIALIZER macro. If you really want.
Post by roland
I hope it is in charge of the implementation of the pthreads
library to release the mutex after last use. Am I correct
with this assumption?
I.e. If I wrap things up so that
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
takes place in my C++ ctor, I have to leave the dtor empty.
pthread_mutex_t is a POD. It doesn't have a dtor.

typedef std::aligned_storage<std::mutex> pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER /* magic */

So to say.
Post by roland
Hmm, this is bad, because it would prevent dynamically creating
C++ wrapped mutexes or putting them on the stack.
Use of PTHREAD_MUTEX_INITIALIZER macro is defined for static
storage only, not stack. Use std::mutex on stack. ;-)
Post by roland
I am afraid
I would end with lot of used memory then which only again gets
destroyed on program termination.
Any thoughts?
http://groups.google.de/groups?selm=412533CA.82703A04%40web.de

regards,
alexander.
roland
2004-12-20 17:16:47 UTC
Permalink
Post by Alexander Terekhov
[...]
Post by roland
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
Who is responsible of deallocation then?
Not sure what you mean. You can call pthread_mutex_destroy() on
a statically allocated pthread_mutex_t object initialized by
PTHREAD_MUTEX_INITIALIZER macro. If you really want.
This is not what I am speaking about.
My book of pthreads (O'Reilly) says:
Dynamically Initializing a Single Mutex Lock:

pthread_mutex_t* mutexp;

.
.
.

mutexp = (pthread_mutex_t*)malloc(sizeof(pthread_mutex_t));
pthread_mutex_init(mutex, NULL);


and later I assume (this is not in the book)
pthread_mutex_destroy(mutexp);
free(mutexp); // to regain the memory

Now, when I use PTHREAD_MUTEX_INITIALIZER this seems
different. Obviously I don't need to care about the
memory allocation? Don't I?

But to get back to my original problem:
When viewed from a C perspective this would be
equvalent to the following usage of the pthread_t type:

void foo() {
pthread_mutex_t mm;
mm = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mm);
}

I guess this usage is not covered by the standard.
But exactly this would happen IMO if I had:

struct mutex {
mutex() mm(PTHREAD_MUTEX_INITIALIZER) {}
~mutex() {} // what should be put there?
// Or may I omit the destroy?
private:
pthread_mutex_t mm;
};

On the other hand:

class mutex
{
mutex(){
pthread_mutex_init(&m_mutex, 0);
}
~mutex() {
pthread_mutex_destroy(&m_mutex);
}
private:
pthread_mutex_t m_mutex;
};

risks the init function beeing called before main.
Is this ok? I mean the posix standard is about C not C++
isn't it?
And it seems this isn't pure academic, since I have seen
a user reporting a problem with this (on unix I assume),
altough I have not yet managed to reproduce it.

So my question basically boils down to:
How should a pthread mutex be correctly wrapped in C++?
Post by Alexander Terekhov
pthread_mutex_t is a POD. It doesn't have a dtor.
This is obvious.
Post by Alexander Terekhov
typedef std::aligned_storage<std::mutex> pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER /* magic */
So to say.
What do you mean by that? I do not know of std::mutex?
Do I miss something important?
Post by Alexander Terekhov
Use of PTHREAD_MUTEX_INITIALIZER macro is defined for static
storage only, not stack. Use std::mutex on stack. ;-)
I understand this.
But again please tell me about this std::mutex thing?
Or do you mean in C++ there would be two different kinds
of mutex be necessary? One for stack and dynamic and one for global usage?
Post by Alexander Terekhov
http://groups.google.de/groups?selm=412533CA.82703A04%40web.de
Hmm, I do see a lot of uncommented code that also references
std::mutex. It seems to have to do with the problem, but perhaps
I am simply too stupid to find the relevance. I would be glad
if you could give me a helping hand.

Roland
Alexander Terekhov
2004-12-20 17:53:47 UTC
Permalink
roland wrote:
[...]
Post by roland
Now, when I use PTHREAD_MUTEX_INITIALIZER this seems
different. Obviously I don't need to care about the
memory allocation? Don't I?
You don't.
Post by roland
When viewed from a C perspective this would be
void foo() {
pthread_mutex_t mm;
mm = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mm);
}
I guess this usage is not covered by the standard.
Yep.
Post by roland
struct mutex {
mutex() mm(PTHREAD_MUTEX_INITIALIZER) {}
This usage is also not covered by the standard.
Post by roland
~mutex() {} // what should be put there?
// Or may I omit the destroy?
pthread_mutex_t mm;
};
class mutex
{
mutex(){
pthread_mutex_init(&m_mutex, 0);
}
~mutex() {
pthread_mutex_destroy(&m_mutex);
}
pthread_mutex_t m_mutex;
};
risks the init function beeing called before main.
Well, calling any pthread function before main is not covered
by any standard, to begin with.
Post by roland
Is this ok? I mean the posix standard is about C not C++
isn't it?
Yep.
Post by roland
And it seems this isn't pure academic, since I have seen
a user reporting a problem with this (on unix I assume),
altough I have not yet managed to reproduce it.
How should a pthread mutex be correctly wrapped in C++?
See below.
Post by roland
Post by Alexander Terekhov
pthread_mutex_t is a POD. It doesn't have a dtor.
This is obvious.
Post by Alexander Terekhov
typedef std::aligned_storage<std::mutex> pthread_mutex_t;
#define PTHREAD_MUTEX_INITIALIZER /* magic */
So to say.
What do you mean by that? I do not know of std::mutex?
That's the problem.
Post by roland
Do I miss something important?
Post by Alexander Terekhov
Use of PTHREAD_MUTEX_INITIALIZER macro is defined for static
storage only, not stack. Use std::mutex on stack. ;-)
I understand this.
But again please tell me about this std::mutex thing?
Or do you mean in C++ there would be two different kinds
of mutex be necessary? One for stack and dynamic and one for global usage?
http://groups.google.de/groups?selm=3ED1E663.B9C89A4F%40web.de

regards,
alexander.
Giancarlo Niccolai
2004-12-20 23:53:51 UTC
Permalink
Post by Alexander Terekhov
[...]
Post by roland
Now, when I use PTHREAD_MUTEX_INITIALIZER this seems
different. Obviously I don't need to care about the
memory allocation? Don't I?
You don't.
Little background explanation needed here.
Mr. Terekhov is a paladin of the "never destroy a mutex" paradigm; honestly,
I'm with him. (**)

His (and mine) theory (I hope to have read correctly his mind;) is that
mutexes are important resources which existence you plan in advance, and
that they are so important in the workflow of your program that they can be
considered fixed assets. As you don't create new functions while the
program is running, you should not create mutexes like mad. Once you have
mutexes guarding your logic, supposing that your logic does not changes,
then there is no reason to change your mutexes.

However, modern programming may require flexible and everchanging program
logic. It is unlikely you have it in a work-horse program for daily jobs,
but you may have it in scripts and script interpreters, highly configurable
programs that may change the behavior at runtime, evolutionary computing
and so on(***). So if you are writing a library (or a standard as posix
does), as well as if you are writing one of such flexible apps, you have to
consider synch objects creation and destruction.

BUT, the problem is not that hairy as it may seem: in a lib, you just
provide the functionality to create and destroy sync primitives correctly,
so, you don't actually do that, just provide for that being possibly done.

In a flexible program, you MUST (and MUST, and MUST, and MUST), work on the
sync prims creation and destroy as if you were in ST. That is, the
configuration and re-logic work must be done in a fashion that allows you
to create sync prims, and destroy the old ones, being able to demonstrate
that there's no user for the old one being destroyed nor for the new ones
not yet ready. This means that the agent or subsystem that is taking care
about that is sure (or makes sure) that no other thread may be disturbing
it in that moment. So, you are creating and destroying sync prims as if you
were in the main() function, or if not, your program is dead.
Post by Alexander Terekhov
Post by roland
When viewed from a C perspective this would be
void foo() {
pthread_mutex_t mm;
mm = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mm);
}
I guess this usage is not covered by the standard.
Yep.
In fact, it has no sense to initialize a mutex and immediately use it. What
would it synchronize if there isn't any possible user?

(also, the practice of locking a mutex, starting a thread that tries to lock
that mutex, and then freeing the mutex in the parent is a WRONG way to try
have the child thread running only after the parent has done something.
Don't do it).
Post by Alexander Terekhov
Well, calling any pthread function before main is not covered
by any standard, to begin with.
Calling any function before main is not covered by ANY standard.
It is a C++ Great Evil, and the same Stroustrup advises strongly against it.
But as sometime Evil may be useful (see C++ FAQ about EVIL meaning), the
COFU semantic has been invented to make it -at least- not breaking your
program.
Post by Alexander Terekhov
Post by roland
Is this ok? I mean the posix standard is about C not C++
isn't it?
Yep.
Yes, but this is not so meaningful as it may seem; see below.
Post by Alexander Terekhov
Post by roland
And it seems this isn't pure academic, since I have seen
a user reporting a problem with this (on unix I assume),
altough I have not yet managed to reproduce it.
How should a pthread mutex be correctly wrapped in C++?
It can, although is not necessary.

However, for how much you wrap it into C++, you have to use it as the
standard or wise practice suggests (or sometimes dictates):
- in usual work-horse programs, create them and never destroy them; you
don't need it.
- in flexible programs, use creation/destruction in a "local main" fashon;
be sure that there's a tight control of the lifespan of the agents so that
when creating/destroying sync objects wrapping primitives there's no agents
that may use them. The function/method/thing that works with primitive
creation/destruction (or wrapping objects creation destruction) must be
like a main() for the agents it manages. This does not prevents other
things to run together with it, as long as its control domain is clean,
(hence the name of "local main"; local with respect to its control domain).


Is it now clear?

Giancarlo.


(**) Someone (I think to remember it was Terekov) reported that posix
committee had a strong internal battle about even introducing the function
to destroy objects. Many were against them, and what we have now is a sort
of "pact".

(***) However, many of this "flexible" programs may be reduced to more
static one just with smarter logic; this is often the case of DBMS (with
stored procedures) and web servers (having bound-in script interpreters).
Alexander Terekhov
2004-12-21 11:43:37 UTC
Permalink
Giancarlo Niccolai wrote:
[...]
Post by Giancarlo Niccolai
Mr. Terekhov is a paladin of the "never destroy a mutex" paradigm;
Uhmm. No.
Post by Giancarlo Niccolai
honestly, I'm with him. (**)
Oh, that's OK. ;-)

regards,
alexander.
roland
2004-12-21 00:17:18 UTC
Permalink
Post by Alexander Terekhov
[...]
Post by roland
Now, when I use PTHREAD_MUTEX_INITIALIZER this seems
different. Obviously I don't need to care about the
memory allocation? Don't I?
You don't.
Post by roland
When viewed from a C perspective this would be
void foo() {
pthread_mutex_t mm;
mm = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_lock(&mm);
}
I guess this usage is not covered by the standard.
Yep.
Otherwise
ftp://sources.redhat.com/pub/pthreads-win32/sources/pthreads-snap-2004-11-22/ptw32_mutex_check_need_init.c
and consequently
ftp://sources.redhat.com/pub/pthreads-win32/sources/pthreads-snap-2004-11-22/pthread_mutex_init.c
would not have been possible.
In this implementation there are some dynamic allocations within
pthread_mutex_init. This implementation simply seems to hand memory
release over to the CRT or the OS then?
I think a polite app would call pthread_destroy (which I suppose
will release memory too?)
Post by Alexander Terekhov
Well, calling any pthread function before main is not covered
by any standard, to begin with.
This is what I suspected. :-(

Was Giancarlo Niccolai wrong with
"Yes, pthread_* objects may be initialized before main" ?
Post by Alexander Terekhov
Post by roland
How should a pthread mutex be correctly wrapped in C++?
See below.
[...]
Post by roland
What do you mean by that? I do not know of std::mutex?
That's the problem.
Post by roland
Do I miss something important?
[...]
http://groups.google.de/groups?selm=3ED1E663.B9C89A4F%40web.de
Ok, so there is no std::mutex yet. However I am aware of quite
some parts of these discussions. Altough I did not know this
particular one.

But I still cannot see how it answers my question.
Do you mean
1) there is no answer, don't try to do multithreading with C++
2) the standards are currently so broken, so hands off
3) Use the pthreads API, don't try to wrap it in C++
4) You (Alexander) know the answer, but leave the solution as homework
to me

I guess you already know my question indeed is about the pthreads
wrapping as is currently done in boost. I think its broken, and
your statements confirm my suspicion.
I would be very glad if you could contribute your valuable experience.
(I know you have!)
But it might also be that you have good reasons not to do so.

What I will try to do to solve the problem is to use kind of a
delayed call to pthread_mutex_init on first use similar to
what happens in result to PTHREAD_MUTEX_INITIALIZER in the
ptw32 implementation, since this implementation seems not to
be limited by the letters of the standard.
I.e.
struct mutex {
mutex() mm(PTHREAD_MUTEX_INITIALIZER) {}
~mutex() { pthread_mutex_destroy(&mm)}
private:
pthread_mutex_t mm;
};
Would be ok in this implementation. (Right?)

This way pthread can be called correctly while C++ wrapping
is possible too.

If you know a more elegant solution please let me know.

reagards,
Roland
Giancarlo Niccolai
2004-12-21 00:24:16 UTC
Permalink
Post by roland
This is what I suspected. :-(
Was Giancarlo Niccolai wrong with
"Yes, pthread_* objects may be initialized before main" ?
I cite myself:


Calling any function before main is not covered by ANY standard.
It is a C++ Great Evil, and the same Stroustrup advises strongly against it.
But as sometime Evil may be useful (see C++ FAQ about EVIL meaning), the
COFU semantic has been invented to make it -at least- not breaking your
program.

---
I add here: I am with Stroustrup: avoid it like plague. But if you really
have to do it, then, use COFU.

(another way to do it would be setting compiler initialization priority via
#pragma, but it's hacky and not portable. I guess it's a matter of tastes,
or of project specifics).
Post by roland
I.e.
struct mutex {
mutex() mm(PTHREAD_MUTEX_INITIALIZER) {}
~mutex() { pthread_mutex_destroy(&mm)}
pthread_mutex_t mm;
};
Would be ok in this implementation. (Right?)
More or less, it's the way to go. It's not in the class, it's in the way you
use it.

Gian.
roland
2004-12-21 01:01:19 UTC
Permalink
Post by Giancarlo Niccolai
Post by roland
I.e.
struct mutex {
mutex() mm(PTHREAD_MUTEX_INITIALIZER) {}
~mutex() { pthread_mutex_destroy(&mm)}
pthread_mutex_t mm;
};
Would be ok in this implementation. (Right?)
More or less, it's the way to go. It's not in the class, it's in the way you
use it.
Perhaps I begin to understand. Even the above still suffers
from ctor initialization order. :-(

A pthread_t seems necessarily to be a POD then, and is not
wrappable in a safe way for use in _any_ C++ library then. :-(

regards,
Roland
Giancarlo Niccolai
2004-12-21 01:18:35 UTC
Permalink
Post by roland
Post by Giancarlo Niccolai
Post by roland
I.e.
struct mutex {
mutex() mm(PTHREAD_MUTEX_INITIALIZER) {}
~mutex() { pthread_mutex_destroy(&mm)}
pthread_mutex_t mm;
};
Would be ok in this implementation. (Right?)
More or less, it's the way to go. It's not in the class, it's in the way
you use it.
Perhaps I begin to understand. Even the above still suffers
from ctor initialization order. :-(
A pthread_t seems necessarily to be a POD then, and is not
wrappable in a safe way for use in _any_ C++ library then. :-(
I can't see why not.
1) You should not use static scoped dynamic initializers for objects using
sync prims (that means, no static objects with complex constructors
please).
2) If you do, use COFU semantic to avoid initialization order fiasco (as
everything else, not just pthread_ things).
3) If you use COFU, be sure that the objects COFUed GETS initialized in
main, if they are not initialized before.

The point 3) is easy. Just call all the COFU functions as soon as you enter
the main, or before you start any thread. There may be more sophisticated
solutions, but they are useless.

However, again, the beauty of threading is not in the library, but is in how
you organize your agents. With the exclusion of avoiding your program to
blow at startup in the case you REALLY need static objects with lock
statements in their constructors (and I am sure you can do something to
avoid them), this problem is just meaningless. You'll soon realize.

plz read:

http://www.niccolai.ws/works/articoli/art-multithreading-en-1a.html

you'll understand that you are focusing on the wrong problem. Don't solve
it, you don't need it to do good threading in c++.

Gian.
Alexander Terekhov
2004-12-21 11:37:09 UTC
Permalink
roland wrote:
[...]
Post by roland
ftp://sources.redhat.com/pub/pthreads-win32/sources/pthreads-snap-2004-11-22/ptw32_mutex_check_need_init.c
and consequently
ftp://sources.redhat.com/pub/pthreads-win32/sources/pthreads-snap-2004-11-22/pthread_mutex_init.c
would not have been possible.
Pthread-win32's statically initialized mutexes are busted. They
should have coded something*** along the lines of

http://groups.google.de/groups?selm=3FA61F96.223FDE85%40web.de

(fallback to something global in the case of event init failure
aside for a moment).
Post by roland
In this implementation there are some dynamic allocations within
pthread_mutex_init. This implementation simply seems to hand memory
release over to the CRT or the OS then?
Sort of.
Post by roland
I think a polite app would call pthread_destroy (which I suppose
will release memory too?)
Well, it can.

[...]
Post by roland
If you know a more elegant solution please let me know.
Stick to statically initialized pthread_mutex_t PODs and be prepared
that your first call might fail due to lack of resources. QoI so to
say (I mean lack of fallback to something global).

regards,
alexander.

***) LL/LR-SC version mimicking CAS-based stuff (without DCSI):

http://sources.redhat.com/ml/pthreads-win32/2004/msg00120.html
Giancarlo Niccolai
2004-12-20 23:21:52 UTC
Permalink
Post by roland
Post by Tom Widmer
Post by Giancarlo Niccolai
Post by roland
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13
But I suggest you to read the whole chapter carefully.
But dynamically initialized static local variables are not threadsafe.
If two threads call the function at the same time (and it hasn't been
called before), there is a race condition over initialization of the
static variable (a mutex in this case). It may end up being initialized
twice, with the two threads using different copies!
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
You can have it as a static variable in a function, but there isn't much
point, since it is initialized at compile time (static rather than
dynamic initialization) in such a way that the first time it is locked,
any runtime initialization that needs to be done is done in a thread
safe way.
That means
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
It is not. As you read in my other reply, this is thread safe, but not
static init safe; you have no threading before main, so you have no need to
be thread safe. What you need is that your mutex is initialized before any
static constructor uses it, and this instruction does nothing to grant
that.
Post by roland
Who is responsible of deallocation then?
I reply to this after Mr. terekhov (next threads), which is right as always,
but a little cryptic for a newby...

Gian.
Giancarlo Niccolai
2004-12-20 23:18:45 UTC
Permalink
Post by Tom Widmer
Post by Giancarlo Niccolai
Post by roland
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13
But I suggest you to read the whole chapter carefully.
But dynamically initialized static local variables are not threadsafe.
If two threads call the function at the same time (and it hasn't been
called before), there is a race condition over initialization of the
static variable (a mutex in this case). It may end up being initialized
twice, with the two threads using different copies!
You are right, but you completely missed the point. You are right because,
in fact, cares should be taken because "construct on first use" for mutex
objects (or objects having mutexes/sync objects in their structure) is
NEVER called in an MT context. IF you think carefully, you'll realize that
allowing concurrent agents to create their own synchronization objects is
not a wise idea... the synch objects must be ready before the threads using
them are create.

What constructs on first use can do (and the only thing it can do), is to
make sure that the data in a class is ready by the time it is first used
during static object initialization, whether the compiler has decided to
initialize it before or after other things that may use it.

Putting it simpler: COFU is NOT for agents, is for static objects that may
fire before main, and that are by their very definition run in single
threading.

The problem at stake here is not that concurrent agents must be able to
initialize their mutexes when they first use it, the problem is avoiding to
feed an invalid mutex into a pthread_mutex_lock() that is INSIDE one
constructor being fired at startup. In that case, COFU will make just sure
that the initialization order fiasco does not happen, initializing mutexes
before they are used.

Once you reach the main() procedure, you are safe: you are in control of
what has been initialized or not, and you can take care to initialize what
has not yet been built.
Post by Tom Widmer
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
Threadsafe, yes, but static init order unsafe. Your compiler may execute
this AFTER that another static object constructor uses this mutex (even if
we are at startup, and even if there's no threading, pthread_mutex_lock()
may still be used i.e. by a constructor that may be used both for a static
object and for objects created by MT agents).
Post by Tom Widmer
You can have it as a static variable in a function, but there isn't much
point, since it is initialized at compile time (static rather than
dynamic initialization) in such a way that the first time it is locked,
any runtime initialization that needs to be done is done in a thread
safe way.
Again, you are not to the point. There may be a constructor firing before
main and using a mutex that has not been yet initialized.

Avoiding using uninitialized mutex at thread time is easy: you just
initialize them in main, or at a safe point before starting threads. The
hard thing is having them initialized BEFORE main...

Gian.
Marcin 'Qrczak' Kowalczyk
2004-12-21 00:28:18 UTC
Permalink
Post by Giancarlo Niccolai
Post by roland
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
Threadsafe, yes, but static init order unsafe. Your compiler may
execute this AFTER that another static object constructor uses this
mutex (even if we are at startup, and even if there's no threading,
pthread_mutex_lock() may still be used i.e. by a constructor that
may be used both for a static object and for objects created by MT
agents).
Since pthreads are usable in C, PTHREAD_MUTEX_INITIALIZER is very
likely to have the same expansion for C and C++. This means that it
probably doesn't use a constructor but a POD initializer, which is
guaranteed to be in effect before constructors are run.
--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Giancarlo Niccolai
2004-12-21 00:49:18 UTC
Permalink
Post by Marcin 'Qrczak' Kowalczyk
Post by Giancarlo Niccolai
Post by roland
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
Threadsafe, yes, but static init order unsafe. Your compiler may
execute this AFTER that another static object constructor uses this
mutex (even if we are at startup, and even if there's no threading,
pthread_mutex_lock() may still be used i.e. by a constructor that
may be used both for a static object and for objects created by MT
agents).
Since pthreads are usable in C, PTHREAD_MUTEX_INITIALIZER is very
likely to have the same expansion for C and C++. This means that it
probably doesn't use a constructor but a POD initializer, which is
guaranteed to be in effect before constructors are run.
1) This is compiler dependant and
2) I was referring (also) to that initializer put inside a constructor for
an object having a mutex in its structure.

(3 threads are not built on "very likely", but "mathematically
proveable" ;-)

Gian.
Marcin 'Qrczak' Kowalczyk
2004-12-21 08:17:40 UTC
Permalink
Post by Giancarlo Niccolai
Post by Marcin 'Qrczak' Kowalczyk
Since pthreads are usable in C, PTHREAD_MUTEX_INITIALIZER is very
likely to have the same expansion for C and C++. This means that it
probably doesn't use a constructor but a POD initializer, which is
guaranteed to be in effect before constructors are run.
1) This is compiler dependant and
Using pthreads with C++ is compiler dependant to start with. We can
only say about what works in practice, there are no standards which
give us any guarantees here.
Post by Giancarlo Niccolai
2) I was referring (also) to that initializer put inside a
constructor for an object having a mutex in its structure.
This does not have to work. It doesn't on my Linux in particular,
where PTHREAD_MUTEX_INITIALIZER is { }, which is not a valid
expression to put in constructor initializer list.
--
__("< Marcin Kowalczyk
\__/ ***@knm.org.pl
^^ http://qrnik.knm.org.pl/~qrczak/
Giancarlo Niccolai
2004-12-21 09:21:09 UTC
Permalink
Post by Marcin 'Qrczak' Kowalczyk
Post by Giancarlo Niccolai
Post by Marcin 'Qrczak' Kowalczyk
Since pthreads are usable in C, PTHREAD_MUTEX_INITIALIZER is very
likely to have the same expansion for C and C++. This means that it
probably doesn't use a constructor but a POD initializer, which is
guaranteed to be in effect before constructors are run.
1) This is compiler dependant and
Using pthreads with C++ is compiler dependant to start with. We can
only say about what works in practice, there are no standards which
give us any guarantees here.
Sorry, I meant implementation dependant; wording mistake.
Post by Marcin 'Qrczak' Kowalczyk
Post by Giancarlo Niccolai
2) I was referring (also) to that initializer put inside a
constructor for an object having a mutex in its structure.
This does not have to work. It doesn't on my Linux in particular,
where PTHREAD_MUTEX_INITIALIZER is { }, which is not a valid
expression to put in constructor initializer list.
Never meant constructor initializer list; when I say constructor, I mean its
body (which can get called if an object is statically declared right before
main).

Giancarlo.
Tom Widmer
2004-12-21 10:08:25 UTC
Permalink
Post by Giancarlo Niccolai
Post by Tom Widmer
Post by Giancarlo Niccolai
Post by roland
Post by Giancarlo Niccolai
3) if the above method cannot be used, use "construct on first use"
semantic. Search google C++ FAQ LITE for an explanation of this semantic.
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.13
But I suggest you to read the whole chapter carefully.
But dynamically initialized static local variables are not threadsafe.
If two threads call the function at the same time (and it hasn't been
called before), there is a race condition over initialization of the
static variable (a mutex in this case). It may end up being initialized
twice, with the two threads using different copies!
You are right, but you completely missed the point. You are right because,
in fact, cares should be taken because "construct on first use" for mutex
objects (or objects having mutexes/sync objects in their structure) is
NEVER called in an MT context. IF you think carefully, you'll realize that
allowing concurrent agents to create their own synchronization objects is
not a wise idea... the synch objects must be ready before the threads using
them are create.
What constructs on first use can do (and the only thing it can do), is to
make sure that the data in a class is ready by the time it is first used
during static object initialization, whether the compiler has decided to
initialize it before or after other things that may use it.
Putting it simpler: COFU is NOT for agents, is for static objects that may
fire before main, and that are by their very definition run in single
threading.
The problem at stake here is not that concurrent agents must be able to
initialize their mutexes when they first use it, the problem is avoiding to
feed an invalid mutex into a pthread_mutex_lock() that is INSIDE one
constructor being fired at startup. In that case, COFU will make just sure
that the initialization order fiasco does not happen, initializing mutexes
before they are used.
You can start threads before main is entered (in so far as C++
implementations let you).
Post by Giancarlo Niccolai
Post by Tom Widmer
pthread_mutex_t global_mutex = PTHREAD_MUTEX_INITIALIZER;
Threadsafe, yes, but static init order unsafe. Your compiler may execute
this AFTER that another static object constructor uses this mutex (even if
we are at startup, and even if there's no threading, pthread_mutex_lock()
may still be used i.e. by a constructor that may be used both for a static
object and for objects created by MT agents).
If that is at global scope, it will be initialized statically. That is,
before the constructors of any global objects run. Although there is no
standard covering the use of pthreads in C++, common sense must be used,
along with knowledge of how all implementations work.
PTHREAD_MUTEX_INITIALIZER is a compile time constant, and as such, where
it is used as an initializer of a POD object of static storage duration
(like pthread_mutex_t), the initializer will run before any dynamic
initialization. See 3.6.2/1 of the C++ standard.
Post by Giancarlo Niccolai
Post by Tom Widmer
You can have it as a static variable in a function, but there isn't much
point, since it is initialized at compile time (static rather than
dynamic initialization) in such a way that the first time it is locked,
any runtime initialization that needs to be done is done in a thread
safe way.
Again, you are not to the point. There may be a constructor firing before
main and using a mutex that has not been yet initialized.
If the mutex has static storage duration, this is impossible - the
program never gets to see it in an uninitialized state.
Post by Giancarlo Niccolai
Avoiding using uninitialized mutex at thread time is easy: you just
initialize them in main, or at a safe point before starting threads. The
hard thing is having them initialized BEFORE main...
It isn't hard at all. This is the whole purpose of
PTHREAD_MUTEX_INITIALIZER, to perform static initialization of variables
with static storage duration.

There is another obvious usage pattern:

A& A::instance() //singleton function
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //static
mutex_guard cerberos(mutex); //unlocks on destruction
static A instance; //dynamic
return a;
}

That's a perfectly threadsafe way of writing a singleton instance method
in so far as it works on C++ implementations where pthreads is available
(there's no standard covering it of course).

Tom
Giancarlo Niccolai
2004-12-21 15:12:39 UTC
Permalink
Post by Tom Widmer
You can start threads before main is entered (in so far as C++
implementations let you).
You could, if you have them started by constructors, but that is under your
complete control. IMHO, it is just a suicide to do so, and you can easily
and safely avoid it by setting a global variable in main an reading it in
the constructors: if the variable is not zero, start the thread, if it is
(zero is the POD init value), just do everything without starting threads.

Pirelli says power is nothing without control. Until you reach main, you
have very limited control. Starting threads in constructors that may be
called at dynamic init time is very alike firing gun cannons while sitting
in front of them...
Post by Tom Widmer
If that is at global scope, it will be initialized statically. That is,
before the constructors of any global objects run. Although there is no
standard covering the use of pthreads in C++, common sense must be used,
along with knowledge of how all implementations work.
PTHREAD_MUTEX_INITIALIZER is a compile time constant, and as such, where
it is used as an initializer of a POD object of static storage duration
(like pthread_mutex_t), the initializer will run before any dynamic
initialization. See 3.6.2/1 of the C++ standard.
Yes; and also classes may be POD if they are also composed of pods (see the
same standard at the /2 paragraph), so even classes having mutexes can be
initialized right if they are POD. If you read my postings, you will notice
I was talking about using at init time non-POD objects HAVING sych
primitives in them. No one ever questioned the fact that a pod mutex
initialization is safe. Is initializing mutexes from constructors at
dynamic init time that is unsafe, if other objects may use it (but
actually, using other objects's data from constructors at init time is
anyhow unsafe if not COFUed, that is what I sustained).
Post by Tom Widmer
Post by Giancarlo Niccolai
Post by Tom Widmer
You can have it as a static variable in a function, but there isn't much
point, since it is initialized at compile time (static rather than
dynamic initialization) in such a way that the first time it is locked,
any runtime initialization that needs to be done is done in a thread
safe way.
Again, you are not to the point. There may be a constructor firing before
main and using a mutex that has not been yet initialized.
If the mutex has static storage duration, this is impossible - the
program never gets to see it in an uninitialized state.
And again, I was talking about a mutex being put in a non-pod structure.
Post by Tom Widmer
Post by Giancarlo Niccolai
Avoiding using uninitialized mutex at thread time is easy: you just
initialize them in main, or at a safe point before starting threads. The
hard thing is having them initialized BEFORE main...
It isn't hard at all. This is the whole purpose of
PTHREAD_MUTEX_INITIALIZER, to perform static initialization of variables
with static storage duration.
Sorry, but again the context of the sentence was referred to non-pod
structures holding mutexes.
Post by Tom Widmer
A& A::instance() //singleton function
{
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; //static
mutex_guard cerberos(mutex); //unlocks on destruction
static A instance; //dynamic
return a;
}
Which is a COFU. So we agree.

Gian.

(PS. but mutex_guard is destroyed as soon as ::instance ends... and it
unlocks a mutex which no-one has locked. Am I missing something?)
Loading...