Post by Alexander Terekhov[...]
Post by rolandNow, 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 TerekhovPost by rolandWhen 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 TerekhovWell, 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 TerekhovPost by rolandIs 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 TerekhovPost by rolandAnd 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).