1 karl 1.30 //%2005////////////////////////////////////////////////////////////////////////
|
2 mike 1.2 //
|
3 karl 1.29 // 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 karl 1.21 // IBM Corp.; EMC Corporation, The Open Group.
|
7 karl 1.29 // Copyright (c) 2004 BMC Software; Hewlett-Packard Development Company, L.P.;
8 // IBM Corp.; EMC Corporation; VERITAS Software Corporation; The Open Group.
|
9 karl 1.30 // Copyright (c) 2005 Hewlett-Packard Development Company, L.P.; IBM Corp.;
10 // EMC Corporation; VERITAS Software Corporation; The Open Group.
|
11 mike 1.2 //
12 // Permission is hereby granted, free of charge, to any person obtaining a copy
|
13 kumpf 1.13 // of this software and associated documentation files (the "Software"), to
14 // deal in the Software without restriction, including without limitation the
15 // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
16 mike 1.2 // sell copies of the Software, and to permit persons to whom the Software is
17 // furnished to do so, subject to the following conditions:
|
18 r.kieninger 1.32 //
|
19 kumpf 1.13 // THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE SHALL BE INCLUDED IN
|
20 mike 1.2 // ALL COPIES OR SUBSTANTIAL PORTIONS OF THE SOFTWARE. THE SOFTWARE IS PROVIDED
21 // "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT
|
22 kumpf 1.13 // LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
23 // PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
24 // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
25 mike 1.2 // ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 //==============================================================================
29 //
30 // Author: Markus Mueller (sedgewick_de@yahoo.de)
31 //
32 // Modified By: Mike Day (mdday@us.ibm.com)
|
33 a.arora 1.23 // Amit K Arora, IBM (amita@in.ibm.com) for PEP#101
|
34 a.arora 1.26 // Alagaraja Ramasubramanian (alags_raj@in.ibm.com) for Bug#1090
|
35 gs.keenan 1.31 // Sean Keenan, Hewlett-Packard Company (sean.keenan@hp.com)
|
36 r.kieninger 1.32 // Robert Kieninger, IBM (kieningr@de.ibm.com)
|
37 mike 1.2 //
38 //%/////////////////////////////////////////////////////////////////////////////
39
40 #include "IPC.h"
41
42 #if defined(PEGASUS_OS_TYPE_WINDOWS)
43 # include "IPCWindows.cpp"
44 #elif defined(PEGASUS_OS_TYPE_UNIX)
|
45 r.kieninger 1.32 # include "IPCUnix.cpp"
|
46 gs.keenan 1.31 #elif defined(PEGASUS_OS_VMS)
47 # include "IPCVms.cpp"
|
48 mike 1.2 #else
49 # error "Unsupported platform"
50 #endif
51
|
52 r.kieninger 1.32 #if defined(PEGASUS_PLATFORM_ZOS_ZSERIES_IBM)
53 #include "IPCzOS.cpp"
54 #endif
55
|
56 kumpf 1.18 #include "InternalException.h"
|
57 dj.gorey 1.25 //#include "NativeCleanup.h"
|
58 mike 1.2
59 PEGASUS_NAMESPACE_BEGIN
60
|
61 r.kieninger 1.32 int timeval_subtract (struct timeval *result,
62 struct timeval *x,
|
63 mday 1.7 struct timeval *y)
64 {
65 /* Perform the carry for the later subtraction by updating Y. */
66 if (x->tv_usec < y->tv_usec) {
67 int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
68 y->tv_usec -= 1000000 * nsec;
69 y->tv_sec += nsec;
70 }
71 if (x->tv_usec - y->tv_usec > 1000000) {
72 int nsec = (x->tv_usec - y->tv_usec) / 1000000;
73 y->tv_usec += 1000000 * nsec;
74 y->tv_sec -= nsec;
75 }
|
76 r.kieninger 1.32
|
77 mday 1.7 /* Compute the time remaining to wait.
78 `tv_usec' is certainly positive. */
79 result->tv_sec = x->tv_sec - y->tv_sec;
80 result->tv_usec = x->tv_usec - y->tv_usec;
|
81 r.kieninger 1.32
|
82 mday 1.7 /* Return 1 if result is negative. */
83 return x->tv_sec < y->tv_sec;
84 }
85
86
87
|
88 mike 1.2 //-----------------------------------------------------------------
89 /// Generic Implementation of read/write semaphore class
90 //-----------------------------------------------------------------
|
91 r.kieninger 1.32 #ifndef PEGASUS_READWRITE_NATIVE
|
92 mike 1.2
93
94 // // If i get cancelled, I MUST ensure:
95 // 1) I do not hold the internal mutex
96 // 2) I do not hold the write lock
97 // 3) I am not using a reader slot
98
99 void extricate_read_write(void *parm)
100 {
101 ReadWriteSem *rws = (ReadWriteSem *)parm;
102 PEGASUS_THREAD_TYPE myself = pegasus_thread_self();
|
103 r.kieninger 1.32
|
104 mike 1.2 if(rws->_rwlock._wlock.get_owner() == myself)
105 rws->_rwlock._wlock.unlock();
106 else
107 if(rws->_readers > 0)
108 rws->_rwlock._rlock.signal();
109 if (rws->_rwlock._internal_lock.get_owner() == myself)
110 rws->_rwlock._internal_lock.unlock();
111 }
|
112 r.kieninger 1.32
|
113 mike 1.2
|
114 mday 1.20 ReadWriteSem::ReadWriteSem(void) : _readers(0), _writers(0), _rwlock() { }
|
115 mike 1.2
116 ReadWriteSem::~ReadWriteSem(void)
117 {
118 // lock everyone out of this object
|
119 r.kieninger 1.32 try
|
120 mike 1.2 {
121 _rwlock._internal_lock.lock(pegasus_thread_self());
122 }
|
123 r.kieninger 1.32 catch(Deadlock& d)
|
124 mike 1.2 {
125 d = d; // no problem - we own the lock, which is what we want
126 }
|
127 r.kieninger 1.32 catch(IPCException& )
|
128 mike 1.2 {
|
129 r.kieninger 1.32 PEGASUS_ASSERT(0);
|
130 mike 1.2 }
|
131 r.kieninger 1.32 while(_readers.value() > 0 || _writers.value() > 0)
|
132 mike 1.2 {
133 pegasus_yield();
134 }
135 _rwlock._internal_lock.unlock();
136 }
137
|
138 dj.gorey 1.25
139
140
141
142
|
143 mike 1.2 //-----------------------------------------------------------------
144 // if milliseconds == -1, wait indefinately
|
145 r.kieninger 1.32 // if milliseconds == 0, fast wait
|
146 mike 1.2 //-----------------------------------------------------------------
|
147 r.kieninger 1.32 void ReadWriteSem::timed_wait(Uint32 mode, PEGASUS_THREAD_TYPE caller, int milliseconds)
|
148 mike 1.2 throw(TimeOut, Deadlock, Permission, WaitFailed, TooManyReaders)
149 {
150
151 //-----------------------------------------------------------------
|
152 r.kieninger 1.32 // Lock this object to maintain integrity while we decide
|
153 mike 1.2 // exactly what to do next.
154 //-----------------------------------------------------------------
|
155 dj.gorey 1.25 // AutoPtr<IPCException> caught;
156 IPCException caught((PEGASUS_THREAD_TYPE)0);
157 WaitFailed caughtWaitFailed((PEGASUS_THREAD_TYPE)0);
158 TimeOut caughtTimeOut((PEGASUS_THREAD_TYPE)0);
159 TooManyReaders caughtTooManyReaders((PEGASUS_THREAD_TYPE)0);
|
160 r.kieninger 1.32
161 { // cleanup stack frame
|
162 mike 1.2 native_cleanup_push(extricate_read_write, this);
163 try
164 {
165 if(milliseconds == 0)
166 _rwlock._internal_lock.try_lock(pegasus_thread_self());
167 else if(milliseconds == -1)
|
168 r.kieninger 1.32 _rwlock._internal_lock.lock(pegasus_thread_self());
|
169 mike 1.2 else
170 _rwlock._internal_lock.timed_lock(milliseconds, pegasus_thread_self());
171 }
|
172 david.dillard 1.28 catch(const IPCException& e)
|
173 mike 1.2 {
|
174 dj.gorey 1.25 caught = e;
|
175 david.dillard 1.28 goto throw_from_here;
|
176 mike 1.2 }
|
177 r.kieninger 1.32
|
178 mike 1.2 if(mode == PEG_SEM_WRITE)
179 {
180 //-----------------------------------------------------------------
181 // Write Lock Step 1: lock the object and allow all the readers to exit
182 //-----------------------------------------------------------------
183
184
185 if(milliseconds == 0) // fast wait
186 {
|
187 mday 1.20 if(_readers.value() > 0)
|
188 mike 1.2 {
189 _rwlock._internal_lock.unlock();
|
190 dj.gorey 1.25 //caught.reset(new WaitFailed(pegasus_thread_self()));
|
191 david.dillard 1.28 caughtWaitFailed = WaitFailed(pegasus_thread_self());
|
192 mike 1.2 goto throw_from_here;
193 }
194 }
|
195 dj.gorey 1.25 else if(milliseconds == -1) // infinite wait
|
196 mike 1.2 {
|
197 mday 1.20 while(_readers.value() > 0 )
|
198 mike 1.2 pegasus_yield();
199 }
|
200 r.kieninger 1.32 else // timed wait
|
201 mike 1.2 {
202 struct timeval start, now;
203 gettimeofday(&start, NULL);
204 start.tv_usec += (1000 * milliseconds);
|
205 mday 1.20 while(_readers.value() > 0)
|
206 mike 1.2 {
207 gettimeofday(&now, NULL);
208 if((now.tv_usec > start.tv_usec) || now.tv_sec > start.tv_sec )
209 {
210 _rwlock._internal_lock.unlock();
|
211 dj.gorey 1.25 //caught.reset(new TimeOut(pegasus_thread_self()));
|
212 david.dillard 1.28 caughtTimeOut = TimeOut(pegasus_thread_self());
|
213 mike 1.2 goto throw_from_here;
214 }
215 pegasus_yield();
216 }
217 }
218 //-----------------------------------------------------------------
219 // Write Lock Step 2: Obtain the Write Mutex
220 // Although there are no readers, there may be a writer
221 //-----------------------------------------------------------------
222 if(milliseconds == 0) // fast wait
223 {
|
224 r.kieninger 1.32 try
|
225 mike 1.2 {
226 _rwlock._wlock.try_lock(pegasus_thread_self());
227 }
|
228 r.kieninger 1.32 catch(IPCException& e)
|
229 mike 1.2 {
230 _rwlock._internal_lock.unlock();
|
231 david.dillard 1.28 caught = e;
|
232 mike 1.2 goto throw_from_here;
233 }
234 }
235 else if(milliseconds == -1) // infinite wait
236 {
|
237 r.kieninger 1.32 try
|
238 mike 1.2 {
239 _rwlock._wlock.lock(pegasus_thread_self());
240 }
|
241 r.kieninger 1.32 catch (const IPCException& e)
|
242 mike 1.2 {
243 _rwlock._internal_lock.unlock();
|
244 david.dillard 1.28 caught = e;
|
245 mike 1.2 goto throw_from_here;
246 }
247 }
248 else // timed wait
249 {
250 try
251 {
252 _rwlock._wlock.timed_lock(milliseconds, pegasus_thread_self());
253 }
|
254 david.dillard 1.28 catch(const IPCException& e)
|
255 mike 1.2 {
256 _rwlock._internal_lock.unlock();
|
257 david.dillard 1.28 caught = e;
|
258 mike 1.2 goto throw_from_here;
259 }
260 }
|
261 david.dillard 1.28
|
262 r.kieninger 1.32 //-----------------------------------------------------------------
|
263 mike 1.2 // Write Lock Step 3: set the writer count to one, unlock the object
264 // There are no readers and we are the only writer !
|
265 r.kieninger 1.32 //-----------------------------------------------------------------
|
266 mike 1.2 _writers = 1;
267 // set the owner
268 _rwlock._owner = pegasus_thread_self();
269 // unlock the object
270 _rwlock._internal_lock.unlock();
271 } // PEG_SEM_WRITE
272 else
273 {
274 //-----------------------------------------------------------------
275 // Read Lock Step 1: Wait for the existing writer (if any) to clear
276 //-----------------------------------------------------------------
277 if(milliseconds == 0) // fast wait
278 {
|
279 mday 1.20 if(_writers.value() > 0)
|
280 mike 1.2 {
281 _rwlock._internal_lock.unlock();
|
282 dj.gorey 1.25 //caught.reset(new WaitFailed(pegasus_thread_self()));
|
283 david.dillard 1.28 caughtWaitFailed = WaitFailed(pegasus_thread_self());
|
284 mike 1.2 goto throw_from_here;
285 }
286 }
287 else if(milliseconds == -1) // infinite wait
288 {
|
289 mday 1.20 while(_writers.value() > 0)
|
290 r.kieninger 1.32 pegasus_yield();
|
291 mike 1.2 }
|
292 david.dillard 1.28 else // timed wait
|
293 mike 1.2 {
294 struct timeval start, now;
295 gettimeofday(&start, NULL);
296 start.tv_usec += (milliseconds * 1000);
|
297 r.kieninger 1.32
|
298 mday 1.20 while(_writers.value() > 0)
|
299 mike 1.2 {
300 gettimeofday(&now, NULL);
301 if((now.tv_usec > start.tv_usec) || (now.tv_sec > start.tv_sec))
302 {
303 _rwlock._internal_lock.unlock();
|
304 dj.gorey 1.25 //caught.reset(new TimeOut(pegasus_thread_self()));
|
305 david.dillard 1.28 caughtTimeOut = TimeOut(pegasus_thread_self());
|
306 mike 1.2 goto throw_from_here;
307 }
308 pegasus_yield();
309 pegasus_gettimeofday(&now);
310 }
311 }
|
312 david.dillard 1.28
|
313 mike 1.2 //-----------------------------------------------------------------
314 // Read Lock Step 2: wait for a reader slot to open up, then return
315 // At this point there are no writers, but there may be too many
316 // readers.
317 //-----------------------------------------------------------------
318 if(milliseconds == 0) // fast wait
319 {
|
320 r.kieninger 1.32 try
|
321 mike 1.2 {
|
322 r.kieninger 1.32 _rwlock._rlock.try_wait();
|
323 mike 1.2 }
|
324 r.kieninger 1.32 catch(const IPCException&)
|
325 mike 1.2 {
|
326 r.kieninger 1.32 // the wait failed, there must be too many readers already.
|
327 mike 1.2 // unlock the object
|
328 david.dillard 1.28 caughtTooManyReaders = TooManyReaders(pegasus_thread_self());
|
329 mike 1.2 _rwlock._internal_lock.unlock();
|
330 dj.gorey 1.25 //caught.reset(new TooManyReaders(pegasus_thread_self()));
|
331 mike 1.2 }
332 }
333 else if(milliseconds == -1) // infinite wait
334 {
|
335 r.kieninger 1.32 try
|
336 mike 1.2 {
|
337 r.kieninger 1.32 _rwlock._rlock.wait();
|
338 mike 1.2 }
|
339 david.dillard 1.28 catch(const IPCException& e)
|
340 mike 1.2 {
341 _rwlock._internal_lock.unlock();
|
342 david.dillard 1.28 caught = e;
343 goto throw_from_here;
|
344 mike 1.2 }
|
345 r.kieninger 1.32 }
|
346 mike 1.2 else // timed wait
347 {
|
348 r.kieninger 1.32 try
|
349 mike 1.2 {
350 _rwlock._rlock.time_wait(milliseconds);
351 }
|
352 david.dillard 1.28 catch(const IPCException& e)
|
353 mike 1.2 {
354 _rwlock._internal_lock.unlock();
|
355 david.dillard 1.28 caught = e;
|
356 mike 1.2 goto throw_from_here;
357 }
358 }
|
359 david.dillard 1.28
|
360 r.kieninger 1.32 //-----------------------------------------------------------------
361 // Read Lock Step 3: increment the number of readers, unlock the object,
|
362 mike 1.2 // return
363 //-----------------------------------------------------------------
364 _readers++;
365 _rwlock._internal_lock.unlock();
366 }
|
367 david.dillard 1.28 throw_from_here:
|
368 mike 1.2 native_cleanup_pop(0);
|
369 r.kieninger 1.32 } // cleanup stack frame
|
370 dj.gorey 1.25
371 if (caught.get_owner() != 0)
372 throw(caught);
|
373 david.dillard 1.28 if (caughtWaitFailed.get_owner() != 0)
|
374 dj.gorey 1.25 throw(caughtWaitFailed);
|
375 david.dillard 1.28 if (caughtTimeOut.get_owner() != 0)
|
376 dj.gorey 1.25 throw(caughtTimeOut);
|
377 david.dillard 1.28 if (caughtTooManyReaders.get_owner() != 0)
|
378 dj.gorey 1.25 throw(caughtTooManyReaders);
|
379 mike 1.2 return;
380 }
381
|
382 dj.gorey 1.25
383
384
385
386 //---------------------------------------------------------------------
|
387 r.kieninger 1.32 void ReadWriteSem::wait(Uint32 mode, PEGASUS_THREAD_TYPE caller)
|
388 mike 1.2 throw(Deadlock, Permission, WaitFailed, TooManyReaders)
389 {
|
390 mday 1.20
|
391 mike 1.2 timed_wait(mode, caller, -1);
392 }
393
|
394 r.kieninger 1.32 void ReadWriteSem::try_wait(Uint32 mode, PEGASUS_THREAD_TYPE caller)
|
395 mike 1.2 throw(Deadlock, Permission, WaitFailed, TooManyReaders)
396 {
397 timed_wait(mode, caller, 0);
398 }
399
400
|
401 r.kieninger 1.32 void ReadWriteSem::unlock(Uint32 mode, PEGASUS_THREAD_TYPE caller)
|
402 mike 1.2 throw(Permission)
403 {
404 if(mode == PEG_SEM_WRITE && _writers.value() != 0 )
405 {
406 _writers = 0;
407 _rwlock._wlock.unlock();
408 }
409 else if (_readers.value() != 0 )
410 {
411 _readers--;
412 _rwlock._rlock.signal();
413 }
414 }
415
416 int ReadWriteSem::read_count()
417
418 {
419 return( _readers.value() );
420 }
421
422 int ReadWriteSem::write_count()
423 mike 1.2 {
424 return( _writers.value() );
425 }
426
427 #endif // ! PEGASUS_READWRITE_NATIVE
428 //-----------------------------------------------------------------
429 // END of generic read/write semaphore implementaion
430 //-----------------------------------------------------------------
431
432
433
434 //-----------------------------------------------------------------
435 /// Generic Implementation of Atomic Integer class
436 //-----------------------------------------------------------------
437
438 #ifndef PEGASUS_ATOMIC_INT_NATIVE
439
|
440 mday 1.8 AtomicInt::AtomicInt() {_rep._value = 0; }
|
441 mike 1.2
|
442 mday 1.8 AtomicInt::AtomicInt(Uint32 initial) {_rep._value = initial; }
|
443 mike 1.2
444 AtomicInt::~AtomicInt()
445 {
446
447 }
448
449 AtomicInt::AtomicInt(const AtomicInt& original)
450 {
451 _rep._value = original._rep._value;
|
452 r.kieninger 1.32 }
|
453 mike 1.2
454 AtomicInt& AtomicInt::operator=(const AtomicInt& original )
455 {
|
456 r.kieninger 1.32 // to avoid deadlocks, always be certain to only hold one mutex at a time.
|
457 mike 1.2 // therefore, get the original value (which will lock and unlock the original's mutex)
458 // and _then_ lock this mutex. This pattern is repeated throughout the class
|
459 r.kieninger 1.32
|
460 mike 1.2 Uint32 temp = original._rep._value;
|
461 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
462 mike 1.2 _rep._value = temp;
|
463 r.kieninger 1.32
|
464 mike 1.2 return *this;
465 }
466
467 AtomicInt& AtomicInt::operator=(Uint32 val)
468 {
|
469 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
470 mike 1.2 _rep._value = val;
|
471 r.kieninger 1.32
|
472 mike 1.2 return *this;
473 }
474
|
475 kumpf 1.14 Uint32 AtomicInt::value(void) const
|
476 mike 1.2 {
|
477 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
478 mike 1.2 Uint32 retval = _rep._value;
|
479 r.kieninger 1.32
|
480 mike 1.2 return retval;
481 }
482
483 void AtomicInt::operator++(void)
484 {
|
485 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
486 mike 1.2 _rep._value++;
|
487 r.kieninger 1.32
|
488 mike 1.2 }
489
490 void AtomicInt::operator++(int)
491 {
|
492 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
493 mike 1.2 _rep._value++;
|
494 r.kieninger 1.32
|
495 mike 1.2 }
496
497 void AtomicInt::operator--(void)
498 {
|
499 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
500 mike 1.2 _rep._value--;
|
501 r.kieninger 1.32
|
502 mike 1.2 }
503
504 void AtomicInt::operator--(int)
505 {
|
506 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
507 mike 1.2 _rep._value--;
|
508 r.kieninger 1.32
|
509 mike 1.2 }
510
511 Uint32 AtomicInt::operator+(const AtomicInt& val)
512 {
|
513 r.kieninger 1.32 // never acquire a mutex while holding a mutex
514 Uint32 retval = val._rep._value;
|
515 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
516 mike 1.2 retval += _rep._value ;
|
517 r.kieninger 1.32
|
518 mike 1.2 return retval;
519 }
520
521 Uint32 AtomicInt::operator+(Uint32 val)
522 {
|
523 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
524 mike 1.2 Uint32 retval = _rep._value + val;
|
525 r.kieninger 1.32
|
526 mike 1.2 return retval;
527 }
528
529 Uint32 AtomicInt::operator-(const AtomicInt& val)
530 {
531 // never acquire a mutex while holding a mutex
532 Uint32 retval = val._rep._value;
|
533 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
534 mike 1.2 retval += _rep._value;
|
535 r.kieninger 1.32
|
536 mike 1.2 return retval;
537 }
538
539 Uint32 AtomicInt::operator-(Uint32 val)
540 {
|
541 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
542 mike 1.2 Uint32 retval = _rep._value - val;
|
543 r.kieninger 1.32
|
544 mike 1.2 return retval;
545 }
546
547
548 AtomicInt& AtomicInt::operator+=(const AtomicInt& val)
549 {
550 // never acquire a mutex while holding a mutex
551 Uint32 temp = val._rep._value;
|
552 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
553 mike 1.2 _rep._value += temp;
|
554 r.kieninger 1.32
|
555 mike 1.2 return *this;
556 }
557 AtomicInt& AtomicInt::operator+=(Uint32 val)
558 {
559 // never acquire a mutex while holding a mutex
|
560 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
561 mike 1.2 _rep._value += val;
|
562 r.kieninger 1.32
|
563 mike 1.2 return *this;
564 }
565
566 AtomicInt& AtomicInt::operator-=(const AtomicInt& val)
567 {
568 // never acquire a mutex while holding a mutex
569 Uint32 temp = val._rep._value;
|
570 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
571 mike 1.2 _rep._value -= temp;
|
572 r.kieninger 1.32
|
573 mike 1.2 return *this;
574 }
575
576 AtomicInt& AtomicInt::operator-=(Uint32 val)
577 {
578 // never acquire a mutex while holding a mutex
|
579 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
580 mike 1.2 _rep._value -= val;
|
581 r.kieninger 1.32
|
582 mike 1.2 return *this;
583 }
584
|
585 kumpf 1.19 Boolean AtomicInt::DecAndTestIfZero()
586 {
|
587 a.arora 1.26 AutoMutex autoMut(_rep._mutex);
|
588 kumpf 1.19 _rep._value--;
589 Boolean b = (_rep._value == 0);
|
590 r.kieninger 1.32
|
591 kumpf 1.19 return b;
592 }
593
|
594 mike 1.2 #endif // ! PEGASUS_ATOMIC_INT_NATIVE
595 //-----------------------------------------------------------------
596 // END of generic atomic integer implementation
597 //-----------------------------------------------------------------
598
599
600
601 //-----------------------------------------------------------------
|
602 r.kieninger 1.32 // Generic implementation of conditional semaphore object
|
603 mike 1.2 //-----------------------------------------------------------------
604 #ifndef PEGASUS_CONDITIONAL_NATIVE
605
606
607 // may be entered by many different threads concurrently
|
608 r.kieninger 1.32 // ensure that, upon exit, I OWN the mutex
|
609 mike 1.2 // and I DO NOT own the critical section
610
611 void extricate_condition(void *parm)
612 {
613 Condition *c = (Condition *)parm;
614
615 // if I own the critical section, release it
616 if(pegasus_thread_self() == c->_condition._spin.get_owner())
617 c->_condition._spin.unlock();
618 // if I DO NOT own the mutex, obtain it
619 if(pegasus_thread_self() != c->_cond_mutex->get_owner())
620 c->_cond_mutex->lock(pegasus_thread_self());
621 }
622
623 Condition::Condition(void) : _disallow(0), _condition()
|
624 r.kieninger 1.32 {
|
625 a.arora 1.23 _cond_mutex.reset(new Mutex());
|
626 mike 1.2 _destroy_mut = true;
|
627 r.kieninger 1.32 }
|
628 mike 1.2
629 Condition::Condition(const Mutex & mutex) : _disallow(0), _condition()
630 {
|
631 a.arora 1.23 _cond_mutex.reset(const_cast<Mutex *>(&mutex));
|
632 mike 1.2 _destroy_mut = false;
633 }
634
635
636 Condition::~Condition(void)
637 {
638 cond_waiter *lingerers;
639 // don't allow any new waiters
640 _disallow++;
|
641 r.kieninger 1.32
|
642 a.arora 1.26 {
643 AutoMutex autoMut(_condition._spin);
|
644 mike 1.2
645 while(NULL != (lingerers = static_cast<cond_waiter *>(_condition._waiters.remove_last())))
646 {
647 lingerers->signalled.signal();
648 }
|
649 a.arora 1.26 } // mutex unlocks here
|
650 r.kieninger 1.32
|
651 mike 1.2 while( _condition._waiters.count()) {
652 pegasus_yield();
653 }
654 if(_destroy_mut == true)
|
655 a.arora 1.23 _cond_mutex.reset();
656 else
657 _cond_mutex.release();
|
658 mike 1.2 }
659
660 void Condition::signal(PEGASUS_THREAD_TYPE caller)
661 throw(IPCException)
662 {
|
663 mday 1.5 _cond_mutex->lock(caller);
|
664 r.kieninger 1.32
|
665 mike 1.2 try
666 {
667 unlocked_signal(caller);
668 }
669 catch(...)
670 {
|
671 mday 1.5 _cond_mutex->unlock();
|
672 mike 1.2 throw;
673 }
|
674 mday 1.5 _cond_mutex->unlock();
|
675 mike 1.2 }
676
677 void Condition::unlocked_signal(PEGASUS_THREAD_TYPE caller)
678 throw(IPCException)
679 {
680 // enforce that the caller owns the conditional lock
681 if(_cond_mutex->_mutex.owner != caller)
682 throw(Permission((PEGASUS_THREAD_TYPE)caller));
683
684 // lock the internal list
685 _condition._spin.lock(caller);
|
686 r.kieninger 1.32 if (_condition._waiters.count() > 0)
|
687 mike 1.2 {
688 cond_waiter *waiters = static_cast<cond_waiter *>(_condition._waiters.next(0));
|
689 r.kieninger 1.32 while( waiters != 0)
|
690 mike 1.2 {
691 waiters->signalled.signal();
692 waiters = static_cast<cond_waiter *>(_condition._waiters.next(waiters));
693 }
694 }
695 _condition._spin.unlock();
696 }
697
|
698 r.kieninger 1.32 void Condition::lock_object(PEGASUS_THREAD_TYPE caller)
|
699 mike 1.2 throw(IPCException)
700 {
|
701 r.kieninger 1.32 if(_disallow.value() > 0)
|
702 mike 1.2 throw ListClosed();
703 _cond_mutex->lock(caller);
704 }
705
706 void Condition::try_lock_object(PEGASUS_THREAD_TYPE caller)
707 throw(IPCException)
708 {
|
709 r.kieninger 1.32 if(_disallow.value() > 0 )
|
710 mike 1.2 throw ListClosed();
711 _cond_mutex->try_lock(caller);
712 }
713
714 void Condition::wait_lock_object(PEGASUS_THREAD_TYPE caller, int milliseconds)
715 throw(IPCException)
716 {
|
717 r.kieninger 1.32 if(_disallow.value() > 0)
|
718 mike 1.2 throw ListClosed();
719 _cond_mutex->timed_lock(milliseconds, caller);
720 }
721
722 void Condition::unlock_object(void)
723 {
724 _cond_mutex->unlock();
725 }
726
|
727 r.kieninger 1.32 void Condition::unlocked_wait(PEGASUS_THREAD_TYPE caller)
|
728 mike 1.2 throw(IPCException)
729 {
730 unlocked_timed_wait(-1, caller);
731 }
732
|
733 r.kieninger 1.32 void Condition::unlocked_timed_wait(int milliseconds, PEGASUS_THREAD_TYPE caller)
|
734 mike 1.2 throw(IPCException)
735 {
736 if(_disallow.value() > 0)
737 {
738 _cond_mutex->unlock();
739 throw ListClosed();
740 }
741 // enforce that the caller owns the conditional lock
742 if(_cond_mutex->_mutex.owner != caller)
743 throw Permission((PEGASUS_THREAD_TYPE)caller);
744 cond_waiter *waiter = new cond_waiter(caller, milliseconds);
745 {
746 native_cleanup_push(extricate_condition, this);
747 // lock the internal list
748 _condition._spin.lock(caller);
749 _condition._waiters.insert_first(waiter);
|
750 r.kieninger 1.32 // unlock the condition mutex
|
751 mike 1.2 _cond_mutex->unlock();
752 _condition._spin.unlock();
753 if(milliseconds == -1)
754 waiter->signalled.wait();
755 else
|
756 r.kieninger 1.32 try
|
757 mike 1.2 {
758 waiter->signalled.time_wait(milliseconds);
759 }
760 catch(TimeOut &)
761 {
762 _cond_mutex->lock(caller);
763 throw;
764 }
|
765 r.kieninger 1.32
766 _condition._spin.lock(caller);
|
767 mike 1.2 _condition._waiters.remove(waiter);
768 _condition._spin.unlock();
769 delete waiter;
770 _cond_mutex->lock(caller);
771 native_cleanup_pop(0);
772 }
773 return;
774 }
775
776
777
778
779 #endif // PEGASUS_CONDITIONAL_NATIVE
780 //-----------------------------------------------------------------
|
781 r.kieninger 1.32 // END of generic implementation of conditional semaphore object
|
782 mike 1.2 //-----------------------------------------------------------------
783
784 PEGASUS_NAMESPACE_END
|