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

Diff for /pegasus/src/Pegasus/Common/Mutex.cpp between version 1.3.14.8 and 1.9.16.3

version 1.3.14.8, 2006/07/30 23:11:55 version 1.9.16.3, 2007/09/12 03:24:32
Line 29 
Line 29 
 // //
 //============================================================================== //==============================================================================
 // //
 // Author: Mike Brasher (m.brasher@inovadevelopment.com)  
 //  
 //%///////////////////////////////////////////////////////////////////////////// //%/////////////////////////////////////////////////////////////////////////////
  
 #include "Mutex.h" #include "Mutex.h"
Line 42 
Line 40 
  
 //============================================================================== //==============================================================================
 // //
 // PEGASUS_HAVE_PTHREADS  // Mutex implementation with PTHREAD_MUTEX_RECURSIVE feature.
 // //
 //============================================================================== //==============================================================================
  
 #if defined(PEGASUS_HAVE_PTHREADS)  #if defined(PEGASUS_HAVE_PTHREADS) && defined(PEGASUS_HAVE_RECURSIVE_MUTEXES)
  
 static Once _once = PEGASUS_ONCE_INITIALIZER; static Once _once = PEGASUS_ONCE_INITIALIZER;
 static pthread_mutexattr_t _attr; static pthread_mutexattr_t _attr;
Line 61 
Line 59 
 { {
     once(&_once, _init_attr);     once(&_once, _init_attr);
     pthread_mutex_init(&_rep.mutex, &_attr);     pthread_mutex_init(&_rep.mutex, &_attr);
   #if defined(PEGASUS_DEBUG)
       _rep.count = 0;
   #endif
   }
   
   Mutex::Mutex(RecursiveTag)
   {
       once(&_once, _init_attr);
       pthread_mutex_init(&_rep.mutex, &_attr);
   #if defined(PEGASUS_DEBUG)
       _rep.count = 0;
   #endif
   }
   
   Mutex::Mutex(NonRecursiveTag)
   {
       pthread_mutex_init(&_rep.mutex, NULL);
   #if defined(PEGASUS_DEBUG)
       _rep.count = 0;
   #endif
 } }
  
 Mutex::~Mutex() Mutex::~Mutex()
Line 76 
Line 94 
     switch (pthread_mutex_lock(&_rep.mutex))     switch (pthread_mutex_lock(&_rep.mutex))
     {     {
         case 0:         case 0:
   #if defined(PEGASUS_DEBUG)
               _rep.count++;
   #endif
             break;             break;
  
         case EDEADLK:  
             throw Deadlock(ThreadType());  
   
         default:         default:
             throw WaitFailed(ThreadType());              throw WaitFailed(Threads::self());
     }     }
 } }
  
Line 90 
Line 108 
 { {
     PEGASUS_DEBUG_ASSERT(_magic);     PEGASUS_DEBUG_ASSERT(_magic);
  
     switch (pthread_mutex_trylock(&_rep.mutex))      int r = pthread_mutex_trylock(&_rep.mutex);
       if (r == -1)
           r=errno;
       switch (r)
     {     {
         case 0:         case 0:
   #if defined(PEGASUS_DEBUG)
               _rep.count++;
   #endif
             break;             break;
  
         case EBUSY:         case EBUSY:
             throw AlreadyLocked(ThreadType());              throw AlreadyLocked(Threads::self());
   
         case EDEADLK:  
             throw Deadlock(ThreadType());  
  
         default:         default:
             throw WaitFailed(ThreadType());              throw WaitFailed(Threads::self());
     }     }
 } }
  
Line 125 
Line 146 
  
     for (;;)     for (;;)
     {     {
         switch (pthread_mutex_trylock(&_rep.mutex))          int r=pthread_mutex_trylock(&_rep.mutex);
           if (r == -1)
               r = errno;
           switch (r)
         {         {
             case 0:             case 0:
   #if defined(PEGASUS_DEBUG)
                   _rep.count++;
   #endif
                 return;                 return;
  
             case EBUSY:             case EBUSY:
Line 141 
Line 168 
                 break;                 break;
             }             }
  
             case EDEADLK:              default:
                 throw Deadlock(Threads::self());                  throw WaitFailed(Threads::self());
           }
       }
   }
   
   void Mutex::unlock()
   {
       PEGASUS_DEBUG_ASSERT(_magic);
       PEGASUS_DEBUG_ASSERT(_rep.count > 0);
   
   #if defined(PEGASUS_DEBUG)
       _rep.count--;
   #endif
   
       if (pthread_mutex_unlock(&_rep.mutex) != 0)
           throw Permission(Threads::self());
   }
   
   #if defined(PEGASUS_OS_LINUX)
   void Mutex::reinitialize()
   {
       pthread_mutex_init(&_rep.mutex, &_attr);
   #if defined(PEGASUS_DEBUG)
       _rep.count = 0;
   #endif
   }
   #endif
   
   #endif /* PEGASUS_HAVE_PTHREADS && PEGASUS_HAVE_RECURSIVE_MUTEXES */
   
   //==============================================================================
   //
   // Mutex implementation without PTHREAD_MUTEX_RECURSIVE feature.
   //
   //==============================================================================
   
   #if defined(PEGASUS_HAVE_PTHREADS) && !defined(PEGASUS_HAVE_RECURSIVE_MUTEXES)
   
   Mutex::Mutex()
   {
       memset(&_rep, 0, sizeof(_rep));
       _rep.recursive = 1;
       pthread_mutex_init(&_rep.mutex, NULL);
       pthread_cond_init(&_rep.cond, NULL);
       _rep.owner = 0;
       _rep.count = 0;
   }
   
   Mutex::Mutex(RecursiveTag)
   {
       memset(&_rep, 0, sizeof(_rep));
       _rep.recursive = 1;
       pthread_mutex_init(&_rep.mutex, NULL);
       pthread_cond_init(&_rep.cond, NULL);
       _rep.owner = 0;
       _rep.count = 0;
   }
   
   Mutex::Mutex(NonRecursiveTag)
   {
       memset(&_rep, 0, sizeof(_rep));
       _rep.recursive = 0;
       pthread_mutex_init(&_rep.mutex, NULL);
   }
   
   Mutex::~Mutex()
   {
       PEGASUS_DEBUG_ASSERT(_magic);
       pthread_mutex_destroy(&_rep.mutex);
   
       if (_rep.recursive)
           pthread_cond_destroy(&_rep.cond);
   }
   
   void Mutex::lock()
   {
       PEGASUS_DEBUG_ASSERT(_magic);
   
       if (_rep.recursive)
       {
           pthread_t self = pthread_self();
   
           pthread_mutex_lock(&_rep.mutex);
           {
               if (_rep.count == 0)
               {
                   _rep.owner = self;
               }
               else if (!pthread_equal(_rep.owner, self))
               {
                   while (_rep.count > 0)
                       pthread_cond_wait(&_rep.cond, &_rep.mutex);
   
                   _rep.owner = self;
               }
   
               _rep.count++;
           }
           pthread_mutex_unlock(&_rep.mutex);
       }
       else
       {
           if (pthread_mutex_lock(&_rep.mutex) != 0)
           {
               throw WaitFailed(Threads::self());
           }
       }
   }
   
   void Mutex::try_lock()
   {
       PEGASUS_DEBUG_ASSERT(_magic);
   
       if (_rep.recursive)
       {
           pthread_t self = pthread_self();
   
           pthread_mutex_lock(&_rep.mutex);
           {
               if (_rep.count == 0)
               {
                   _rep.owner = self;
                   _rep.count = 1;
               }
               else if (pthread_equal(_rep.owner, self))
               {
                   _rep.count++;
               }
               else
               {
                   pthread_mutex_unlock(&_rep.mutex);
                   throw AlreadyLocked(Threads::self());
               }
           }
           pthread_mutex_unlock(&_rep.mutex);
       }
       else
       {
           int r = pthread_mutex_trylock(&_rep.mutex);
   
           if (r == -1)
               r = errno;
   
           switch (r)
           {
               case 0:
                   break;
   
               case EBUSY:
                   throw AlreadyLocked(Threads::self());
   
               default:
                   throw WaitFailed(Threads::self());
           }
       }
   }
   
   void Mutex::timed_lock(Uint32 milliseconds)
   {
       PEGASUS_DEBUG_ASSERT(_magic);
   
       if (_rep.recursive)
       {
           pthread_t self = pthread_self();
   
           pthread_mutex_lock(&_rep.mutex);
           {
               if (_rep.count == 0)
               {
                   _rep.owner = self;
               }
               else if (!pthread_equal(_rep.owner, self))
               {
                   timespec ts;
                   clock_gettime(CLOCK_REALTIME, &ts);
   
                   ts.tv_sec += milliseconds / 1000;
                   ts.tv_nsec += (milliseconds % 1000) * 1000000;
   
                   while (_rep.count > 0)
                   {
                       if (pthread_cond_timedwait(
                           &_rep.cond, &_rep.mutex, &ts) != 0)
                       {
                           pthread_mutex_unlock(&_rep.mutex);
                           throw TimeOut(Threads::self());
                       }
                   }
   
                   _rep.owner = self;
               }
   
               _rep.count++;
           }
           pthread_mutex_unlock(&_rep.mutex);
       }
       else
       {
           struct timeval now;
           struct timeval finish;
           struct timeval remaining;
           {
               Uint32 usec;
               gettimeofday(&finish, NULL);
               finish.tv_sec += (milliseconds / 1000 );
               milliseconds %= 1000;
               usec = finish.tv_usec + ( milliseconds * 1000 );
               finish.tv_sec += (usec / 1000000);
               finish.tv_usec = usec % 1000000;
           }
   
           for (;;)
           {
               int r = pthread_mutex_trylock(&_rep.mutex);
   
               if (r == -1)
                   r = errno;
   
               switch (r)
               {
                   case 0:
                       return;
   
                   case EBUSY:
                   {
                       gettimeofday(&now, NULL);
   
                       if (Time::subtract(&remaining, &finish, &now))
                           throw TimeOut(Threads::self());
   
                       Threads::yield();
                       break;
                   }
  
             default:             default:
                 throw WaitFailed(Threads::self());                 throw WaitFailed(Threads::self());
         }         }
     }     }
 } }
   }
  
 void Mutex::unlock() void Mutex::unlock()
 { {
     PEGASUS_DEBUG_ASSERT(_magic);     PEGASUS_DEBUG_ASSERT(_magic);
  
       if (_rep.recursive)
       {
           pthread_t self = pthread_self();
   
           pthread_mutex_lock(&_rep.mutex);
           {
               // If not locked or if calling thread is not the locker.
   
               if (_rep.count == 0 || !pthread_equal(_rep.owner, self))
                   PEGASUS_DEBUG_ASSERT(0);
   
               _rep.count--;
               _rep.owner = 0;
   
               pthread_cond_signal(&_rep.cond);
           }
           pthread_mutex_unlock(&_rep.mutex);
       }
       else
       {
     if (pthread_mutex_unlock(&_rep.mutex) != 0)     if (pthread_mutex_unlock(&_rep.mutex) != 0)
         throw Permission(ThreadType());              throw Permission(Threads::self());
       }
 } }
  
 #endif /* PEGASUS_HAVE_PTHREADS */  #endif /* PEGASUS_HAVE_PTHREADS && !PEGASUS_HAVE_RECURSIVE_MUTEXES */
  
 //============================================================================== //==============================================================================
 // //
Line 168 
Line 449 
  
 #if defined(PEGASUS_HAVE_WINDOWS_THREADS) #if defined(PEGASUS_HAVE_WINDOWS_THREADS)
  
   static inline void _initialize(MutexRep& rep)
   {
       rep.handle = CreateMutex(NULL, FALSE, NULL);
       rep.count = 0;
   }
   
 Mutex::Mutex() Mutex::Mutex()
 { {
     _rep.handle = CreateMutex(NULL, FALSE, NULL);      _initialize(_rep);
     Threads::clear(ThreadType());  }
     _rep.count = 0;  
   Mutex::Mutex(RecursiveTag)
   {
       _initialize(_rep);
   }
   
   Mutex::Mutex(NonRecursiveTag)
   {
       _initialize(_rep);
 } }
  
 Mutex::~Mutex() Mutex::~Mutex()
Line 190 
Line 485 
     DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);     DWORD rc = WaitForSingleObject(_rep.handle, INFINITE);
  
     if (rc == WAIT_FAILED)     if (rc == WAIT_FAILED)
         throw WaitFailed(ThreadType());          throw WaitFailed(Threads::self());
  
     _rep.count++;     _rep.count++;
 } }
Line 202 
Line 497 
     DWORD rc = WaitForSingleObject(_rep.handle, 0);     DWORD rc = WaitForSingleObject(_rep.handle, 0);
  
     if (rc == WAIT_TIMEOUT)     if (rc == WAIT_TIMEOUT)
         throw AlreadyLocked(ThreadType());          throw AlreadyLocked(Threads::self());
  
     if (rc == WAIT_FAILED)     if (rc == WAIT_FAILED)
         throw WaitFailed(ThreadType());          throw WaitFailed(Threads::self());
  
     _rep.count++;     _rep.count++;
 } }
Line 217 
Line 512 
     DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);     DWORD rc = WaitForSingleObject(_rep.handle, milliseconds);
  
     if (rc == WAIT_TIMEOUT)     if (rc == WAIT_TIMEOUT)
         throw TimeOut(ThreadType());          throw TimeOut(Threads::self());
  
     if (rc == WAIT_FAILED)     if (rc == WAIT_FAILED)
         throw WaitFailed(ThreadType());          throw WaitFailed(Threads::self());
  
     _rep.count++;     _rep.count++;
 } }
Line 228 
Line 523 
 void Mutex::unlock() void Mutex::unlock()
 { {
     PEGASUS_DEBUG_ASSERT(_magic);     PEGASUS_DEBUG_ASSERT(_magic);
       PEGASUS_DEBUG_ASSERT(_rep.count > 0);
  
     Threads::clear(ThreadType());  
     _rep.count--;     _rep.count--;
     ReleaseMutex(_rep.handle);     ReleaseMutex(_rep.handle);
 } }


Legend:
Removed from v.1.3.14.8  
changed lines
  Added in v.1.9.16.3

No CVS admin address has been configured
Powered by
ViewCVS 0.9.2