1 karl 1.3 //%2006////////////////////////////////////////////////////////////////////////
|
2 mike 1.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 karl 1.3 // Copyright (c) 2006 Hewlett-Packard Development Company, L.P.; IBM Corp.;
12 // EMC Corporation; Symantec Corporation; The Open Group.
|
13 mike 1.2 //
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 karl 1.3 //
|
21 mike 1.2 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
22 // 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 "Mutex.h"
|
35 mike 1.4 #include "Time.h"
36 #include "PegasusAssert.h"
37 #include "Once.h"
|
38 mike 1.2
39 PEGASUS_NAMESPACE_BEGIN
40
|
41 mike 1.4 //==============================================================================
42 //
43 // PEGASUS_HAVE_PTHREADS
44 //
45 //==============================================================================
46
47 #if defined(PEGASUS_HAVE_PTHREADS)
48
49 static Once _once = PEGASUS_ONCE_INITIALIZER;
50 static pthread_mutexattr_t _attr;
51
52 static void _init_attr()
53 {
54 pthread_mutexattr_init(&_attr);
55 pthread_mutexattr_settype(&_attr, PTHREAD_MUTEX_RECURSIVE);
56 }
57
58 Mutex::Mutex()
59 {
60 once(&_once, _init_attr);
61 pthread_mutex_init(&_rep.mutex, &_attr);
62 mike 1.4 #if defined(PEGASUS_DEBUG)
63 _rep.count = 0;
64 #endif
65 }
66
|
67 mike 1.6 Mutex::Mutex(RecursiveTag)
68 {
69 once(&_once, _init_attr);
70 pthread_mutex_init(&_rep.mutex, &_attr);
71 #if defined(PEGASUS_DEBUG)
72 _rep.count = 0;
73 #endif
74 }
75
76 Mutex::Mutex(NonRecursiveTag)
77 {
78 pthread_mutex_init(&_rep.mutex, NULL);
79 #if defined(PEGASUS_DEBUG)
80 _rep.count = 0;
81 #endif
82 }
83
|
84 mike 1.4 Mutex::~Mutex()
85 {
86 PEGASUS_DEBUG_ASSERT(_magic);
87 pthread_mutex_destroy(&_rep.mutex);
88 }
89
90 void Mutex::lock()
91 {
92 PEGASUS_DEBUG_ASSERT(_magic);
93
94 switch (pthread_mutex_lock(&_rep.mutex))
95 {
96 case 0:
97 #if defined(PEGASUS_DEBUG)
98 _rep.count++;
99 #endif
100 break;
101
102 default:
103 throw WaitFailed(Threads::self());
104 }
105 mike 1.4 }
106
107 void Mutex::try_lock()
108 {
109 PEGASUS_DEBUG_ASSERT(_magic);
110
|
111 marek 1.5 int r = pthread_mutex_trylock(&_rep.mutex);
112 if (r == -1)
113 r=errno;
114 switch (r)
|
115 mike 1.4 {
116 case 0:
117 #if defined(PEGASUS_DEBUG)
118 _rep.count++;
119 #endif
120 break;
121
122 case EBUSY:
123 throw AlreadyLocked(Threads::self());
124
125 default:
126 throw WaitFailed(Threads::self());
127 }
128 }
129
130 void Mutex::timed_lock(Uint32 milliseconds)
131 {
132 PEGASUS_DEBUG_ASSERT(_magic);
133
134 struct timeval now;
135 struct timeval finish;
136 mike 1.4 struct timeval remaining;
137 {
138 Uint32 usec;
139 gettimeofday(&finish, NULL);
140 finish.tv_sec += (milliseconds / 1000 );
141 milliseconds %= 1000;
142 usec = finish.tv_usec + ( milliseconds * 1000 );
143 finish.tv_sec += (usec / 1000000);
144 finish.tv_usec = usec % 1000000;
145 }
146
147 for (;;)
148 {
|
149 marek 1.5 int r=pthread_mutex_trylock(&_rep.mutex);
150 if (r == -1)
151 r = errno;
152 switch (r)
|
153 mike 1.4 {
154 case 0:
155 #if defined(PEGASUS_DEBUG)
156 _rep.count++;
157 #endif
158 return;
159
160 case EBUSY:
161 {
162 gettimeofday(&now, NULL);
163
164 if (Time::subtract(&remaining, &finish, &now))
165 throw TimeOut(Threads::self());
166
167 Threads::yield();
168 break;
169 }
170
171 default:
172 throw WaitFailed(Threads::self());
173 }
174 mike 1.4 }
175 }
176
177 void Mutex::unlock()
178 {
179 PEGASUS_DEBUG_ASSERT(_magic);
180 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
181
182 #if defined(PEGASUS_DEBUG)
183 _rep.count--;
184 #endif
185
186 if (pthread_mutex_unlock(&_rep.mutex) != 0)
187 throw Permission(Threads::self());
188 }
189
190 #endif /* PEGASUS_HAVE_PTHREADS */
191
192 //==============================================================================
193 //
194 // PEGASUS_HAVE_WINDOWS_THREADS
195 mike 1.4 //
196 //==============================================================================
197
198 #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
199
|
200 mike 1.7 static inline void _initialize(MutexRep& rep)
201 {
202 rep.handle = CreateMutex(NULL, FALSE, NULL);
203 #if defined(PEGASUS_DEBUG)
204 rep.count = 0;
205 #endif
206 }
207
|
208 mike 1.4 Mutex::Mutex()
209 {
|
210 mike 1.7 _initialize(_rep);
211 }
212
|
213 mike 1.6 Mutex::Mutex(RecursiveTag)
214 {
|
215 mike 1.7 _initialize(_rep);
|
216 mike 1.6 }
217
218 Mutex::Mutex(NonRecursiveTag)
219 {
|
220 mike 1.7 _initialize(_rep);
|
221 mike 1.4 }
222
223 Mutex::~Mutex()
224 {
225 PEGASUS_DEBUG_ASSERT(_magic);
226
227 WaitForSingleObject(_rep.handle, INFINITE);
228 CloseHandle(_rep.handle);
229 }
230
231 void Mutex::lock()
232 {
233 PEGASUS_DEBUG_ASSERT(_magic);
234
235 DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
236
237 if (rc == WAIT_FAILED)
238 throw WaitFailed(Threads::self());
239
240 #if defined(PEGASUS_DEBUG)
241 _rep.count++;
242 mike 1.4 #endif
243 }
244
245 void Mutex::try_lock()
246 {
247 PEGASUS_DEBUG_ASSERT(_magic);
248
249 DWORD rc = WaitForSingleObject(_rep.handle, 0);
250
251 if (rc == WAIT_TIMEOUT)
252 throw AlreadyLocked(Threads::self());
253
254 if (rc == WAIT_FAILED)
255 throw WaitFailed(Threads::self());
256
257 #if defined(PEGASUS_DEBUG)
258 _rep.count++;
259 #endif
260 }
261
262 void Mutex::timed_lock(Uint32 milliseconds)
263 mike 1.4 {
264 PEGASUS_DEBUG_ASSERT(_magic);
265
266 DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
267
268 if (rc == WAIT_TIMEOUT)
269 throw TimeOut(Threads::self());
270
271 if (rc == WAIT_FAILED)
272 throw WaitFailed(Threads::self());
273
274 #if defined(PEGASUS_DEBUG)
275 _rep.count++;
276 #endif
277 }
278
279 void Mutex::unlock()
280 {
281 PEGASUS_DEBUG_ASSERT(_magic);
282 PEGASUS_DEBUG_ASSERT(_rep.count > 0);
283
284 mike 1.4 #if defined(PEGASUS_DEBUG)
285 _rep.count--;
286 #endif
287 ReleaseMutex(_rep.handle);
288 }
289
290 #endif /* PEGASUS_HAVE_WINDOWS_THREADS */
291
|
292 mike 1.2 PEGASUS_NAMESPACE_END
|