CHSM  4.4.1
pjl_threads.h
1 /*
2 ** PJL C++ Library
3 ** pjl_threads.h
4 **
5 ** Copyright (C) 1998 Paul J. Lucas
6 **
7 ** This program is free software; you can redistribute it and/or modify
8 ** it under the terms of the GNU General Public License as published by
9 ** the Free Software Foundation; either version 2 of the License, or
10 ** (at your option) any later version.
11 **
12 ** This program is distributed in the hope that it will be useful,
13 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ** GNU General Public License for more details.
16 **
17 ** You should have received a copy of the GNU General Public License
18 ** along with this program; if not, write to the Free Software
19 ** Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21 
22 #ifndef pjl_threads_H
23 #define pjl_threads_H
24 
25 // standard
26 #ifdef CHSM_MULTITHREADED
27 #include <pthread.h>
28 #endif
29 
30 #ifdef CHSM_MULTITHREADED
31 //
32 // Macros to wrap critical sections.
33 //
34 #define DEFER_CANCEL() \
35  { int pjl_cancel_type; \
36  ::pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &pjl_cancel_type )
37 
38 #define RESTORE_CANCEL() \
39  ::pthread_setcanceltype( pjl_cancel_type, 0 ); \
40  ::pthread_testcancel(); }
41 
42 #else /* CHSM_MULTITHREADED */
43 
44 #define DEFER_CANCEL() /* nothing */
45 #define RESTORE_CANCEL() /* nothing */
46 
47 #endif /* CHSM_MULTITHREADED */
48 
49 #ifdef CHSM_MULTITHREADED
50 //
51 // Define a more robust mutex locking mechanism by ensuring that the mutex will
52 // be unlocked even if the thread is cancelled. Also roll in optional critical
53 // section protection since we're doing pthread_setcanceltype() anyway.
54 //
55 // See also: Bradford Nichols, Dick Buttlar, and Jacqueline Proulx Farrell.
56 // "Pthreads Programming," O'Reilly & Associates, Sebastopol, CA, 1996.
57 // pp. 141-142.
58 //
59 #define MUTEX_LOCK(M,D) { \
60  int pjl_cancel_type; bool const pjl_defer_cancel = (D); \
61  ::pthread_setcanceltype( PTHREAD_CANCEL_DEFERRED, &pjl_cancel_type ); \
62  pthread_cleanup_push( (void (*)(void*))::pthread_mutex_unlock, (M) ); \
63  ::pthread_mutex_lock( (M) ); \
64  if ( D ) ; else { \
65  ::pthread_setcanceltype( pjl_cancel_type, 0 ); \
66  ::pthread_testcancel(); \
67  }
68 
69 #define MUTEX_UNLOCK() \
70  pthread_cleanup_pop( 1 ); \
71  if ( pjl_defer_cancel ) { \
72  ::pthread_setcanceltype( pjl_cancel_type, 0 ); \
73  ::pthread_testcancel(); \
74  } \
75  }
76 
77 #else /* CHSM_MULTITHREADED */
78 
79 #define MUTEX_LOCK(M,D) /* nothing */
80 #define MUTEX_UNLOCK() /* nothing */
81 
82 #endif /* CHSM_MULTITHREADED */
83 
84 #endif /* pjl_threads_H */
85 /* vim:set et sw=4 ts=4: */