]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/rdwr.c
56de51cf944ca352e415d9ff0c5218b53bee5cf2
[openldap] / libraries / libldap_r / rdwr.c
1 /*
2 ** This basic implementation of Reader/Writer locks does not
3 ** protect writers from starvation.  That is, if a writer is
4 ** currently waiting on a reader, any new reader will get
5 ** the lock before the writer.
6 */
7
8 /********************************************************
9  * An example source module to accompany...
10  *
11  * "Using POSIX Threads: Programming with Pthreads"
12  *               by Brad nichols, Dick Buttlar, Jackie Farrell
13  *               O'Reilly & Associates, Inc.
14  *
15  ********************************************************
16  * rdwr.c --
17  * 
18  * Library of functions implementing reader/writer locks
19  */
20
21 #include "portable.h"
22
23 #include <stdlib.h>
24
25 #include "ldap_pvt_thread.h"
26
27 int 
28 ldap_pvt_thread_rdwr_init(ldap_pvt_thread_rdwr_t *rdwrp )
29 {
30         rdwrp->lt_readers_reading = 0;
31         rdwrp->lt_writer_writing = 0;
32         ldap_pvt_thread_mutex_init(&(rdwrp->lt_mutex) );
33         ldap_pvt_thread_cond_init(&(rdwrp->lt_lock_free) );
34         return 0;
35 }
36
37 int 
38 ldap_pvt_thread_rdwr_destroy(ldap_pvt_thread_rdwr_t *rdwrp )
39 {
40         ldap_pvt_thread_mutex_destroy(&(rdwrp->lt_mutex) );
41         ldap_pvt_thread_cond_destroy(&(rdwrp->lt_lock_free) );
42         return 0;
43 }
44
45 int ldap_pvt_thread_rdwr_rlock(ldap_pvt_thread_rdwr_t *rdwrp){
46         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
47         while(rdwrp->lt_writer_writing) {
48                 ldap_pvt_thread_cond_wait(&(rdwrp->lt_lock_free), 
49                                           &(rdwrp->lt_mutex));
50         }
51         rdwrp->lt_readers_reading++;
52         ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
53         return 0;
54 }
55
56 int ldap_pvt_thread_rdwr_runlock(ldap_pvt_thread_rdwr_t *rdwrp)
57 {
58         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
59         if (rdwrp->lt_readers_reading == 0) {
60                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
61                 return -1;
62         }
63         else {
64                 rdwrp->lt_readers_reading--;
65                 if (rdwrp->lt_readers_reading == 0) {
66                         ldap_pvt_thread_cond_signal(&(rdwrp->lt_lock_free));
67                 }
68                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
69                 return 0;
70         }
71 }
72
73 int ldap_pvt_thread_rdwr_wlock(ldap_pvt_thread_rdwr_t *rdwrp)
74 {
75         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
76         while(rdwrp->lt_writer_writing || rdwrp->lt_readers_reading) {
77                 ldap_pvt_thread_cond_wait(&(rdwrp->lt_lock_free), 
78                                           &(rdwrp->lt_mutex));
79         }
80         rdwrp->lt_writer_writing++;
81         ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
82         return 0;
83 }
84
85 int ldap_pvt_thread_rdwr_wunlock(ldap_pvt_thread_rdwr_t *rdwrp)
86 {
87         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
88         if (rdwrp->lt_writer_writing == 0) {
89                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
90                 return -1;
91         }
92         else {
93                 rdwrp->lt_writer_writing = 0;
94                 ldap_pvt_thread_cond_broadcast(&(rdwrp->lt_lock_free));
95                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
96                 return 0;
97         }
98 }
99
100 #ifdef LDAP_DEBUG
101
102 /* just for testing, 
103  * return 0 if false, suitable for assert(ldap_pvt_thread_rdwr_Xchk(rdwr))
104  * 
105  * Currently they don't check if the calling thread is the one 
106  * that has the lock, just that there is a reader or writer.
107  *
108  * Basically sufficent for testing that places that should have
109  * a lock are caught.
110  */
111
112 int ldap_pvt_thread_rdwr_rchk(ldap_pvt_thread_rdwr_t *rdwrp)
113 {
114         return(rdwrp->lt_readers_reading!=0);
115 }
116
117 int ldap_pvt_thread_rdwr_wchk(ldap_pvt_thread_rdwr_t *rdwrp)
118 {
119         return(rdwrp->lt_writer_writing!=0);
120 }
121 int ldap_pvt_thread_rdwr_rwchk(ldap_pvt_thread_rdwr_t *rdwrp)
122 {
123         return(ldap_pvt_thread_rdwr_rchk(rdwrp) || 
124                ldap_pvt_thread_rdwr_wchk(rdwrp));
125 }
126
127 #endif /* LDAP_DEBUG */