]> git.sur5r.net Git - openldap/blob - libraries/libldap_r/rdwr.c
1d43efc0756b2294807a46c318895837c05f8758
[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 ldap_pvt_thread_rdwr_rlock(ldap_pvt_thread_rdwr_t *rdwrp){
38         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
39         while(rdwrp->lt_writer_writing) {
40                 ldap_pvt_thread_cond_wait(&(rdwrp->lt_lock_free), 
41                                           &(rdwrp->lt_mutex));
42         }
43         rdwrp->lt_readers_reading++;
44         ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
45         return 0;
46 }
47
48 int ldap_pvt_thread_rdwr_runlock(ldap_pvt_thread_rdwr_t *rdwrp)
49 {
50         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
51         if (rdwrp->lt_readers_reading == 0) {
52                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
53                 return -1;
54         }
55         else {
56                 rdwrp->lt_readers_reading--;
57                 if (rdwrp->lt_readers_reading == 0) {
58                         ldap_pvt_thread_cond_signal(&(rdwrp->lt_lock_free));
59                 }
60                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
61                 return 0;
62         }
63 }
64
65 int ldap_pvt_thread_rdwr_wlock(ldap_pvt_thread_rdwr_t *rdwrp)
66 {
67         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
68         while(rdwrp->lt_writer_writing || rdwrp->lt_readers_reading) {
69                 ldap_pvt_thread_cond_wait(&(rdwrp->lt_lock_free), 
70                                           &(rdwrp->lt_mutex));
71         }
72         rdwrp->lt_writer_writing++;
73         ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
74         return 0;
75 }
76
77 int ldap_pvt_thread_rdwr_wunlock(ldap_pvt_thread_rdwr_t *rdwrp)
78 {
79         ldap_pvt_thread_mutex_lock(&(rdwrp->lt_mutex));
80         if (rdwrp->lt_writer_writing == 0) {
81                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
82                 return -1;
83         }
84         else {
85                 rdwrp->lt_writer_writing = 0;
86                 ldap_pvt_thread_cond_broadcast(&(rdwrp->lt_lock_free));
87                 ldap_pvt_thread_mutex_unlock(&(rdwrp->lt_mutex));
88                 return 0;
89         }
90 }
91
92 #ifdef LDAP_DEBUG
93
94 /* just for testing, 
95  * return 0 if false, suitable for assert(ldap_pvt_thread_rdwr_Xchk(rdwr))
96  * 
97  * Currently they don't check if the calling thread is the one 
98  * that has the lock, just that there is a reader or writer.
99  *
100  * Basically sufficent for testing that places that should have
101  * a lock are caught.
102  */
103
104 int ldap_pvt_thread_rdwr_rchk(ldap_pvt_thread_rdwr_t *rdwrp)
105 {
106         return(rdwrp->lt_readers_reading!=0);
107 }
108
109 int ldap_pvt_thread_rdwr_wchk(ldap_pvt_thread_rdwr_t *rdwrp)
110 {
111         return(rdwrp->lt_writer_writing!=0);
112 }
113 int ldap_pvt_thread_rdwr_rwchk(ldap_pvt_thread_rdwr_t *rdwrp)
114 {
115         return(ldap_pvt_thread_rdwr_rchk(rdwrp) || 
116                ldap_pvt_thread_rdwr_wchk(rdwrp));
117 }
118
119 #endif /* LDAP_DEBUG */