1 mike 1.2 //%2006////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (c) 2000, 2001, 2002 BMC Software; Hewlett-Packard Development
4 // Company, L.P.; IBM Corp.; The Open Group; Tivoli Systems.
5 // Copyright (c) 2003 BMC Software; Hewlett-Packard Development Company, L.P.;
6 // IBM Corp.; EMC Corporation, The Open Group.
7 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
9 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
11 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
13 //
14 // Permission is hereby granted, free of charge, to any person obtaining a copy
15 // of this software and associated documentation files (the "Software"), to
16 // deal in the Software without restriction, including without limitation the
17 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
18 // sell copies of the Software, and to permit persons to whom the Software is
19 // furnished to do so, subject to the following conditions:
20 //
21 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
23 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
24 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
25 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
26 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
27 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29 //
30 //==============================================================================
31 //
32 //%/////////////////////////////////////////////////////////////////////////////
33
34 #include "ReadWriteSem.h"
35 #include "Time.h"
36 #include "PegasusAssert.h"
37 #include "Threads.h"
|
38 kumpf 1.13 #include "Exception.h"
39 #include "System.h"
|
40 mike 1.2
41 PEGASUS_NAMESPACE_BEGIN
42
43 //==============================================================================
44 //
45 // PEGASUS_USE_POSIX_RWLOCK
46 //
47 //==============================================================================
48
49 #ifdef PEGASUS_USE_POSIX_RWLOCK
50
|
51 kumpf 1.12 ReadWriteSem::ReadWriteSem()
|
52 mike 1.2 {
53 pthread_rwlock_init(&_rwlock.rwlock, NULL);
54 }
55
56 ReadWriteSem::~ReadWriteSem()
57 {
|
58 kumpf 1.5 int r = 0;
|
59 mike 1.6 while ((r = pthread_rwlock_destroy(&_rwlock.rwlock)) == EBUSY ||
|
60 kumpf 1.5 (r == -1 && errno == EBUSY))
|
61 mike 1.2 {
62 Threads::yield();
63 }
64 }
65
|
66 kumpf 1.12 void ReadWriteSem::waitRead()
|
67 mike 1.2 {
|
68 kumpf 1.13 int r = pthread_rwlock_rdlock(&_rwlock.rwlock);
69
70 if (r != 0)
|
71 mike 1.2 {
|
72 kumpf 1.13 if (r != -1)
73 {
74 // Special behavior for Single UNIX Specification, Version 3
75 errno = r;
76 }
77
78 throw Exception(MessageLoaderParms(
79 "Common.InternalException.READ_LOCK_FAILED",
80 "Failed to acquire read lock: $0",
81 PEGASUS_SYSTEM_ERRORMSG_NLS));
|
82 mike 1.2 }
83 }
84
|
85 kumpf 1.12 void ReadWriteSem::waitWrite()
|
86 mike 1.2 {
|
87 kumpf 1.13 int r = pthread_rwlock_wrlock(&_rwlock.rwlock);
88
89 if (r != 0)
|
90 mike 1.2 {
|
91 kumpf 1.13 if (r != -1)
92 {
93 // Special behavior for Single UNIX Specification, Version 3
94 errno = r;
95 }
96
97 throw Exception(MessageLoaderParms(
98 "Common.InternalException.WRITE_LOCK_FAILED",
99 "Failed to acquire write lock: $0",
100 PEGASUS_SYSTEM_ERRORMSG_NLS));
|
101 mike 1.2 }
|
102 kumpf 1.12 }
|
103 kumpf 1.10
|
104 kumpf 1.12 void ReadWriteSem::unlockRead()
105 {
|
106 kumpf 1.10 int rc = pthread_rwlock_unlock(&_rwlock.rwlock);
107 // All documented error codes represent coding errors.
108 PEGASUS_ASSERT(rc == 0);
|
109 mike 1.2 }
110
|
111 kumpf 1.12 void ReadWriteSem::unlockWrite()
|
112 mike 1.2 {
|
113 kumpf 1.12 int rc = pthread_rwlock_unlock(&_rwlock.rwlock);
114 // All documented error codes represent coding errors.
115 PEGASUS_ASSERT(rc == 0);
|
116 mike 1.2 }
117
118 #endif /* PEGASUS_USE_POSIX_RWLOCK */
119
120 //==============================================================================
121 //
122 // PEGASUS_USE_SEMAPHORE_RWLOCK
123 //
124 //==============================================================================
125
126 #if defined(PEGASUS_USE_SEMAPHORE_RWLOCK)
127
128 // // If i get cancelled, I MUST ensure:
129 // 1) I do not hold the internal mutex
130 // 2) I do not hold the write lock
131 // 3) I am not using a reader slot
132
|
133 kumpf 1.12 ReadWriteSem::ReadWriteSem() : _rwlock()
|
134 mike 1.2 {
135 }
136
137 ReadWriteSem::~ReadWriteSem()
138 {
139 // lock everyone out of this object
140 try
141 {
142 _rwlock._internal_lock.lock();
143 }
|
144 kumpf 1.13 catch (...)
|
145 mike 1.2 {
146 PEGASUS_ASSERT(0);
147 }
|
148 kumpf 1.12 while (_rwlock._readers.get() > 0 || _rwlock._writers.get() > 0)
|
149 mike 1.2 {
150 Threads::yield();
151 }
152 _rwlock._internal_lock.unlock();
153 }
154
|
155 kumpf 1.12 void ReadWriteSem::waitRead()
|
156 mike 1.2 {
|
157 kumpf 1.12 // Lock the internal mutex to ensure only one waiter is processed at a time.
158 AutoMutex lock(_rwlock._internal_lock);
159
160 // Wait for the existing writer (if any) to clear.
161 while (_rwlock._writers.get() > 0)
162 {
163 Threads::yield();
|
164 mike 1.2 }
|
165 kumpf 1.12
166 // Wait for a reader slot to open up.
167 _rwlock._rlock.wait();
168
169 // Increment the number of readers.
170 _rwlock._readers++;
171 }
172
173 void ReadWriteSem::waitWrite()
174 {
175 // Lock the internal mutex to ensure only one waiter is processed at a time.
176 AutoMutex lock(_rwlock._internal_lock);
177
178 // Allow all the readers to exit.
179 while (_rwlock._readers.get() > 0)
180 {
181 Threads::yield();
182 }
183
184 // Obtain the write mutex.
185 _rwlock._wlock.lock();
186 kumpf 1.12
187 // Set the writer count to one.
188 _rwlock._writers = 1;
|
189 mike 1.2 }
190
|
191 kumpf 1.12 void ReadWriteSem::unlockRead()
|
192 mike 1.2 {
|
193 kumpf 1.12 PEGASUS_ASSERT(_rwlock._readers.get() > 0);
194 _rwlock._readers--;
195 _rwlock._rlock.signal();
|
196 mike 1.2 }
197
|
198 kumpf 1.12 void ReadWriteSem::unlockWrite()
|
199 mike 1.2 {
|
200 kumpf 1.12 PEGASUS_ASSERT(_rwlock._writers.get() == 1);
201 _rwlock._writers = 0;
202 _rwlock._wlock.unlock();
|
203 mike 1.2 }
204
205 #endif /* !PEGASUS_USE_SEMAPHORE_RWLOCK */
206
207 PEGASUS_NAMESPACE_END
|