CCAFFEINE
0.8.8
|
00001 /**************************************************************************** 00002 * 00003 * 00004 * File: pth_rwlock.h 00005 * 00006 * Public functions for pth_rwlock.lib 00007 * 00008 * PURPOSE 00009 * 00010 * This package implements a readers/writer lock facility, using the POSIX 00011 * threads package. This is very similar to readers/writer lock facility 00012 * that is part of Solaris native threads, so do 'man rwlock_init' for a 00013 * description. I have tried to name calls similarly, adding a "pth_" prefix 00014 * to indicate that this is associated with, but not part of, the POSIX thread 00015 * package. 00016 * 00017 * This package does not prevent a thread from acquiring the read lock twice, 00018 * such as when a function in your package that holds the lock calls another 00019 * function which tries to acquire the lock. It is important to ensure that 00020 * your application does not do this, as a deadlock can result. 00021 * 00022 * It happens in this way: a thread first takes a read lock, and subsequently 00023 * another thread attempts to acquire a write lock. The writer must wait for 00024 * all readers to yield the lock before proceeding. When the reader tries to 00025 * acquire the read lock again, it notices that a writer is pending, and waits 00026 * to let the write occur. Since it is holding a read lock already, the write 00027 * cannot proceed, and the threads deadlock. 00028 * 00029 * Therefore, you can recognize the deadlock in this way: there are one or 00030 * more active readers, pending readers and pending writers, and the total 00031 * will be more than the number of threads that share the data structure. 00032 * 00033 ***************************************************************************** 00034 */ 00035 #ifndef PTH_RWLOCK_H 00036 #define PTH_RWLOCK_H 00037 00038 #include <pthread.h> 00039 00040 #define pthread_rwlockattr_t void 00041 00042 #ifdef __cplusplus 00043 extern "C" { 00044 #endif 00045 00046 00047 typedef struct pth_rwlock 00048 { 00049 int active_readers;/* -1 when writer active */ 00050 int pending_readers; 00051 int pending_writers; 00052 00053 pthread_mutex_t mutex; 00054 pthread_cond_t ok_to_read; 00055 pthread_cond_t ok_to_write; 00056 } pth_rwlock_t; 00057 00058 00059 /* Initialize a readers/writer lock. 00060 */ 00061 void pth_rwlock_init(pth_rwlock_t * lock, const pthread_rwlockattr_t * attr); 00062 00063 00064 /* Destroy a readers/writer lock. The space used by the rwlock is not freed. 00065 */ 00066 void pth_rwlock_destroy(pth_rwlock_t * lock); 00067 00068 00069 /* Acquire a read-only lock. 00070 */ 00071 void pth_rwlock_rdlock(pth_rwlock_t *lock); 00072 00073 00074 /* Release a read-only lock. 00075 */ 00076 void pth_rwlock_rdunlock(pth_rwlock_t * lock); 00077 00078 00079 /* Acquire a write lock. 00080 */ 00081 void pth_rwlock_wrlock(pth_rwlock_t * lock); 00082 00083 00084 /* Try to get a write lock, without waiting. 00085 * As with pthread_mutex_trylock(), returns 0 on success. 00086 */ 00087 int pth_rwlock_wrtrylock(pth_rwlock_t * lock); 00088 00089 00090 /* pth_rwlock_tryupgrade 00091 * 00092 * Try to upgrade a read lock to a write lock. 00093 * Returns 0 on success, and -1 if there are other active readers. 00094 */ 00095 int pth_rwlock_tryupgrade(pth_rwlock_t * lock); 00096 00097 00098 /* Release a write lock. 00099 */ 00100 void pth_rwlock_wrunlock(pth_rwlock_t * lock); 00101 00102 00103 /* Release a read-only or write lock. 00104 */ 00105 void pth_rwlock_unlock(pth_rwlock_t * lock); 00106 00107 #ifdef __cplusplus 00108 } 00109 #endif 00110 00111 00112 /* 00113 * Some useful macros to put in assert()s. 00114 */ 00115 #define READ_LOCK_HELD(lock)(lock.active_readers > 0) 00116 00117 #define WRITE_LOCK_HELD(lock)(lock.active_readers == -1) 00118 00119 /* 00120 * define pthread_XXX to appropriate symbol defined above 00121 */ 00122 00123 #endif