Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

PTHREAD_STATIC_INITIALIZER, class constructor

67 views
Skip to first unread message

mvitalo

unread,
Oct 10, 2002, 4:39:39 PM10/10/02
to
I was asked this question:

Is this okay?

class Love
{
static const pthread_mutex_t initializer;
pthread_mutex_t m;

public:

Love()
{
m = initializer;
}

void Lock()
{ pthread_mutex_lock( &m ); }

void Unlock()
{ pthread_mutex_unlock( &m ); }
};

const pthread_mutex_t Love::initializer = PTHREAD_MUTEX_INITIALIZER;

The person would like to write code like this:

static Love mutex;


void SuperFunc()
{
Guard guard( mutex );

// some work here...
}

I'm made nervous by this approach because I have never seen code doing this,
which leads me to believe that this is incorrect.

Is this approach okay?

thanks and take care,
mike vitalo

Ian Collins

unread,
Oct 11, 2002, 4:29:13 AM10/11/02
to
mvitalo wrote:
>
> I was asked this question:
>
> Is this okay?
>
> class Love
> {
> static const pthread_mutex_t initializer;
> pthread_mutex_t m;
>
> public:
>
> Love()
> {
> m = initializer;
> }
>
> void Lock()
> { pthread_mutex_lock( &m ); }
>
> void Unlock()
> { pthread_mutex_unlock( &m ); }
> };
>
> const pthread_mutex_t Love::initializer = PTHREAD_MUTEX_INITIALIZER;
>
initializer is a static so it can be initialised with
PTHREAD_MUTEX_INITIALIZER.

But you then use it to intialise a dynamic mutex, m. This is not
correct use of PTHREAD_MUTEX_INITIALIZER.

Why not just use pthread_mutex_init( &m, NULL )?

Ian

> The person would like to write code like this:
>
> static Love mutex;
>
> void SuperFunc()
> {
> Guard guard( mutex );
>
> // some work here...
> }
>
> I'm made nervous by this approach because I have never seen code doing this,
> which leads me to believe that this is incorrect.
>
> Is this approach okay?
>
> thanks and take care,
> mike vitalo

--
Ian Collins
Masuma Ltd,
Christchurch
New Zealand.

Alexander Terekhov

unread,
Oct 11, 2002, 4:48:30 AM10/11/02
to

No. And I'm just curious: what's your problem with pthread_mutex_init()
and/or having C++ scoped locking guards for *pthread_mutex_t* objects?

static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

void SuperFunc()
{
CMutexGuard guard( mutex ); // CMutexGuard::CMutexGuard( pthread_mutex_t& mutex );

// some work here...
}

regards,
alexander.

Momchil Velikov

unread,
Oct 11, 2002, 6:02:46 AM10/11/02
to
mvi...@sprynet.com (mvitalo) wrote in message news:<7601581c.02101...@posting.google.com>...

> class Love
> {
> static const pthread_mutex_t initializer;
> pthread_mutex_t m;
>
> public:
>
> Love()
> {
> m = initializer;
> }
>
> I'm made nervous by this approach because I have never seen code doing this,
> which leads me to believe that this is incorrect.
>
> Is this approach okay?

"This volume of IEEE Std 1003.1-2001 supports several alternative
implementations of mutexes. An implementation may store the lock
directly in the object of type pthread_mutex_t. Alternatively, an
implementation may store the lock in the heap and merely store a
pointer, handle, or unique ID in the mutex object. Either
implementation has advantages or may be required on certain hardware
configurations. So that portable code can be written that is invariant
to this choice, this volume of IEEE Std 1003.1-2001 does not define
assignment or equality for this type, and it uses the term
``initialize'' to reinforce the (more restrictive) notion that the
lock may actually reside in the mutex object itself."

> I'm made nervous by this approach because I have never seen code doing this,
> which leads me to believe that this is incorrect.

Guess that's why.

~velco

Patrick TJ McPhee

unread,
Oct 11, 2002, 12:51:41 AM10/11/02
to
In article <7601581c.02101...@posting.google.com>,
mvitalo <mvi...@sprynet.com> wrote:

% I was asked this question:
%
% Is this okay?
%
% class Love
% {
% static const pthread_mutex_t initializer;
% pthread_mutex_t m;
%
% public:
%
% Love()
% {
% m = initializer;
% }
%
% void Lock()
% { pthread_mutex_lock( &m ); }
%
% void Unlock()
% { pthread_mutex_unlock( &m ); }
% };
%
% const pthread_mutex_t Love::initializer = PTHREAD_MUTEX_INITIALIZER;

No. PTHREAD_MUTEX_INITIALIZER can only be used to initialise a static
value, so the assignment to m is not valid. In practice, it will work on
at least one platform, but it will definitely fail on at least one
other. On the other hand, why not simply call pthread_mutex_init() in
the constructor?


--

Patrick TJ McPhee
East York Canada
pt...@interlog.com

David Butenhof

unread,
Oct 11, 2002, 10:16:39 AM10/11/02
to
mvitalo wrote:

> I was asked this question:
>
> Is this okay?
>
> class Love
> {
> static const pthread_mutex_t initializer;
> pthread_mutex_t m;
>
> public:
>
> Love()
> {
> m = initializer;

Several people have already mentioned that "this isn't a legal use of
PTHREAD_MUTEX_INITIALIZER", because 'm' isn't a static object. For some
reason, though, nobody's mentioned the additional reason this is wrong...
even if 'initializer' had not been initialized using
PTHREAD_MUTEX_INITIALIZER.

POSIX does not allow you to COPY the value of a synchronization object. Or
rather, by C language rules you can make a copy of the TYPE... but the
resulting value is no longer a POSIX synchronization object, just a
collection of bits.

--
/--------------------[ David.B...@hp.com ]--------------------\
| Hewlett-Packard Company Tru64 UNIX & VMS Thread Architect |
| My book: http://www.awl.com/cseng/titles/0-201-63392-2/ |
\----[ http://homepage.mac.com/dbutenhof/Threads/Threads.html ]---/

Dragan Cvetkovic

unread,
Oct 11, 2002, 10:22:35 AM10/11/02
to
David Butenhof <David.B...@compaq.com> writes:
>
> POSIX does not allow you to COPY the value of a synchronization object.

Does not allow (== forbid) or does not guarantee the correct behaviour of
the copied object?

Bye, Dragan

--
Dragan Cvetkovic,

To be or not to be is true. G. Boole No it isn't. L. E. J. Brouwer

mvitalo

unread,
Oct 11, 2002, 10:30:50 AM10/11/02
to
Alexander Terekhov <tere...@web.de> wrote in message news:<3DA6905E...@web.de>...
> mvitalo wrote:

[ snip ]

> > Is this approach okay?
>
> No. And I'm just curious: what's your problem with pthread_mutex_init()
> and/or having C++ scoped locking guards for *pthread_mutex_t* objects?

My suggest was identicle to yours. :-) ( Which makes me feel good! )
However, I'm having to compose this code for others who would preferr
the approach listed in my posting. They like classes and those types
of things, to the level that they would like even the mutex type
to be one. The goal is to encapsulate our use of pthreads so that the
consumer is unaffected by any changes we make there.

thanks and take care,
mike v


>

mvitalo

unread,
Oct 11, 2002, 10:36:46 AM10/11/02
to
pt...@interlog.com (Patrick TJ McPhee) wrote in message news:<xNsp9.14565$qh1.2...@news.ca.inter.net>...

[SNIP]

>
> No. PTHREAD_MUTEX_INITIALIZER can only be used to initialise a static
> value, so the assignment to m is not valid. In practice, it will work on
> at least one platform, but it will definitely fail on at least one
> other. On the other hand, why not simply call pthread_mutex_init() in
> the constructor?

The concern with calling pthread_init() in the construct revolves around
how to handle failure there. We couldn't use exceptions, as we have dissabled
them in our C++. The variable or lock itself is something we need initialized
in a library before the first function exported from it is called. However,
the consumer can call one of many functions and we cannot require them to call
some init() function first.

Dave Butenhof

unread,
Oct 11, 2002, 10:50:13 AM10/11/02
to
Dragan Cvetkovic wrote:

>The following message is a courtesy copy of an article
>that has been posted to comp.programming.threads as well.


>
>David Butenhof <David.B...@compaq.com> writes:
>
>
>>POSIX does not allow you to COPY the value of a synchronization object.
>>
>>
>Does not allow (== forbid) or does not guarantee the correct behaviour of
>the copied object?
>
>

In practice, there's no useful difference, is there? As I said, you can
use the C copy operator on the type, because that's just C and there's
nothing that POSIX can say about it. The copy, however, is not a POSIX
synchronization object. Since there are no defined operations on
pthread_mutex_t aside from the pthread_mutex_* operations, "success" is
irrelevant. ;-)

What POSIX actually says is "Only 'mutex' itself may be used for
performing synchronization. The result of referring to copies of 'mutex'
in calls to pthread_mutex_lock(), pthread_mutex_trylock(),
pthread_mutex_unlock(), and pthread_mutex_detroy() is undefined."

(Actually, that's an error, because it wasn't edited to account for
pthread_mutex_timedlock(). So if you have an implementation that
provides pthread_mutex_timedlock, POSIX says you can use a copy of the
mutex with only that operation. Luckily, that's a loophole nobody can
exploit because you'd just deadlock your application -- you're not
allowed to UNLOCK it. ;-) )

Eric D Crahen

unread,
Oct 11, 2002, 1:32:59 PM10/11/02
to
On 11 Oct 2002, mvitalo wrote:

> However, I'm having to compose this code for others who would preferr
> the approach listed in my posting. They like classes and those types
> of things, to the level that they would like even the mutex type
> to be one. The goal is to encapsulate our use of pthreads so that the
> consumer is unaffected by any changes we make there.

You might to take a look at the source for ZThreads
(zthread.sourceforge.net). I'm using exceptions in that library, but
perhaps the structure and encapsulation I use there will still be of some
help to you.


- Eric
http://www.code-foo.com/

mvitalo

unread,
Oct 11, 2002, 2:50:24 PM10/11/02
to
David Butenhof <David.B...@compaq.com> wrote in message

[ snip ]

> Several people have already mentioned that "this isn't a legal use of
> PTHREAD_MUTEX_INITIALIZER", because 'm' isn't a static object. For some
> reason, though, nobody's mentioned the additional reason this is wrong...
> even if 'initializer' had not been initialized using
> PTHREAD_MUTEX_INITIALIZER.
>
> POSIX does not allow you to COPY the value of a synchronization object. Or
> rather, by C language rules you can make a copy of the TYPE... but the
> resulting value is no longer a POSIX synchronization object, just a
> collection of bits.

Yikes, this is something I never considered! Now I look at things very
differently. I have your book; is this mentioned in it? (I haven't read
it all the way yet.)

thanks,
mike v

Ian Collins

unread,
Oct 11, 2002, 3:40:45 PM10/11/02
to
If you can't use exceptions (why disable them?) you have two choices:

1) add an ok() member to the class and call it to make sure the object
has been constructed correctly
2) abort on error in the constructor. There is not a lot else you can
do if the mutex initialisation fails.

Ian

David Butenhof

unread,
Oct 15, 2002, 8:18:54 AM10/15/02
to
mvitalo wrote:

Yes, though it's maybe too easy to miss if you're skimming quickly. It's in
the first paragraph of "Creating and destroying a mutex", and the
equivalent for condition variables. (There's actually slightly more
discussion in the CV section.) Arguably, I should have put in a big callout
to bring attention to the warning -- but at the time I wrote it, I hadn't
seen many people having trouble with this and I didn't think of it as a
particularly "big deal".

0 new messages