Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Oct 2008 09:46:28 +0800
From:      David Xu <davidxu@freebsd.org>
To:        Daniel Eischen <deischen@freebsd.org>
Cc:        threads@freebsd.org, John Hein <jhein@timing.com>
Subject:   Re: pthread_cleanup_push & pthread_cleanup_pop usage
Message-ID:  <48F69CF4.9050905@freebsd.org>
In-Reply-To: <Pine.GSO.4.64.0810080215150.3378@sea.ntplx.net>
References:  <18668.10465.699531.162573@gromit.timing.com>	<20081008045447.GY36572@elvis.mu.org> <Pine.GSO.4.64.0810080215150.3378@sea.ntplx.net>

next in thread | previous in thread | raw e-mail | index | archive | help
Daniel Eischen wrote:
> On Tue, 7 Oct 2008, Alfred Perlstein wrote:
> 
>> * John Hein <jhein@timing.com> [081007 21:45] wrote:
>>> In June pthread_cleanup_push & pthread_cleanup_pop were changed to 
>>> macros
>>> that look like so...
>>
>> Hey John, I found the same problem when working on QNX a while back,
>> however that is really how it's supposed to be set up.
>>
>> I would suggest the following construct to fix the problem,
>> make your own per-thread stack of destructors that are callable
>> as functions and not macros.
>>
>> It's not too hard to do.
>>
>> Just use a pthread_key and pthread_once thingy to write a library
>> to do it, shouldn't take more than a hundred lines of code.
>>
>> FWIW, OS X and QNX have the same set of macros, not sure about
>> other OSes.
> 
> Solaris as well.
> 
> Just conditionally undef them before you use them.
> 
>     #ifdef pthread_cleanup_push
>     #undef pthread_cleanup_push
>     #endif
>         #ifdef pthread_cleanup_pop
>         #undef pthread_cleanup_pop
>         #endif
> 
> The library versions are still there (they have to be in order
> to be callable from non-C/C++ languages).
> 

One of possible solutions is we define a C++ class in pthread.h:

#ifdef __cplusplus
class __pthread_cleanup_obj {
	void (*__f)(void *);
	void *__a;
	int  __execeute;
public:
	__pthread_cleanup_obj(void (*__cleanup_routine)(void *), void *__arg) {
		f = __cleanup_routine;
		a = __arg;
		__execute = 0;
	}
	~__pthread_cleanup_obj()
	{
		if  (__execute)
			__f(__a);
	}
	
	void __set_execute(int __e)
	{
		__execute = __e;
	}
};

#define pthread_cleanup_push(f, a) {				\
		__pthread_cleanup_obj __cleanup(f, a);		\
                 {

#define pthread_cleanup_pop(e) 					\
		__cleanup.__set_execute(e);		\
		}						\
	}

#endif

but because there is no specification for C++ and threading,
it is unknown which behavior is desired.

David Xu




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?48F69CF4.9050905>