From: http://blog.chinaunix.net/u2/72995/showart_1218514.html void pthread_cleanup_push (void (* routine) (void *), void * Arg );
Void pthread_cleanup_pop (INT execute); // The Int parameter here. 0 indicates that push is not executed, but not 0 indicates execution.
The prototype is very simple, and the function is similar to atexit (), but one is thread and the other is process.
Used to set what to do when the push/pop thread exits.
Notes:
1. Push and pop must appear in pairs. In fact, push contains "{" and pop contains "}", but one less one does not work.
2. There can be multiple pushes, and the same pop should correspond to the number, following the "advanced post-release principle ".
The push function may be executed at the following three times:
1. The displayed call pthread_exit ();
Or
2. The cancel point thread is cancel.
Or
3. When the pthread_cleanup_pop () parameter is not 0.
The above actions are limited to the Code covered by push/pop.
The previous two are easy to understand. The key is the pthread_cleanup_pop parameter. In fact, Int Is because C does not have bool. The parameter here is only the difference between 0 and 0. For pthread_cleanup_pop, the values 5 and 10 are the same and both are non-0.
We often see this Code:
Void child (void * t)
{
Pthread_cleanup_push (pthread_mutex_unlock, & mutex );
Pthread_mutex_lock (& mutex );
..............
Pthread_mutex_unlock (& mutex );
Pthread_cleanup_pop (0 );
}
Why is pthread_cleanup_pop 0? He will not execute the function pointed to by the pointer of the function pushed in. Yes, it is not executed. It is troublesome to execute it.
Why do I have to write this sentence?
This is because push and pop must appear in pairs. If you do not write, it is a syntax error.
The purpose of this write is to ensure that mutex can be unlocked, because anything may happen between pthread_mutex_lock and pthread_mutex_unlock, for example, there are n cancel points, causing the thread to be given to cancel by the main or other threads, while the cancel action will not release the mutex lock, so the lock will be locked.
Use pthread_cleanup_push to add a function pthread_mutex_unlock. Refer to the execution time description above. When the thread is cancel, it can be used to release the lock. If the thread runs properly and knows that it is running to pthread_cleanup_pop, the lock has been released by pthread_mutex_unlock in the intermediate code. If the pthread_cleanup_pop parameter is not 0, it will be released again, the error is reported here and released twice.
Therefore, pthread_cleanup_pop (0) is required, because it must first appear in pairs. Secondly, we do not want it to be released twice.
Likewise:
Void * exit1 (void * t)
{
Printf ("exit1/N ");
}
Void * child (void * t)
{
Pthread_cleanup_push (exit1, null );
.....
Pthread_exit (null );
Pthread_cleanup_pop (0 );
}
The exit1 function is executed at pthread_exit (null). It does not matter if the pthread_cleanup_pop parameter is 0, because it cannot be executed here.
The change is as follows:
Pthread_cleanup_push (exit1, null );
......
Pthread_cleanup_pop (0 );
Pthread_exit (null );
Exit1 will not be executed because the pop parameter is 0. If you change the pop parameter to 1, exit1 will be executed. Will it be executed twice? No, because pthread_exit is outside the push/pop block, it will not trigger exit1.
Pthread_cleanup_push (exit1, null );
Pthread_cleanup_push (exit2, null );
........
Pthread_cleanup_pop (0 );
Pthread_cleanup_pop (1 );
Who respectively controls 0 and 1? Matching Principle: Unplug one pair from the outside to the inside. Obviously, 0 controls exit2.
A test procedure is attached:
#include <stdio.h> #include <pthread.h> #include <unistd.h> #include <stdlib.h>
void clean ( void * p ) { printf ( "clean()/n" ); }
void * thread ( void * p ) {
pthread_cleanup_push( clean, NULL); printf ( "thread sleep/n" ); sleep (10); printf("thread wake.../n"); pthread_cleanup_pop(1); }
int main () { pthread_t id; pthread_mutexattr_t attr; pthread_create ( &id, NULL, thread, NULL ); printf ( "main sleep/n"); sleep(3); printf ( "cancel thread:%u/n", id ); pthread_cancel ( id ); return 0; }
/* Output: Thread sleep Main sleep Cancel thread: 1082399936 Clean () */
|