(file) Return to IPC.cpp CVS log (file) (dir) Up to [Pegasus] / pegasus / src / Pegasus / Common

  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

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2