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