CrystalSpace

Public API Reference

csutil/threading/pthread_mutex.h

00001 /*
00002   Copyright (C) 2006 by Marten Svanfeldt
00003 
00004   This library is free software; you can redistribute it and/or
00005   modify it under the terms of the GNU Lesser General Public
00006   License as published by the Free Software Foundation; either
00007   version 2 of the License, or (at your option) any later version.
00008 
00009   This library is distributed in the hope that it will be useful,
00010   but WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012   Library General Public License for more details.
00013 
00014   You should have received a copy of the GNU Library General Public
00015   License along with this library; if not, write to the Free
00016   Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00017 */
00018 
00019 #ifndef __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__
00020 #define __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__
00021 
00022 #ifndef DOXYGEN_RUN
00023 
00024 #include <pthread.h>
00025 
00026 namespace CS
00027 {
00028 namespace Threading
00029 {
00030 namespace Implementation
00031 {
00032   class ConditionBase;
00033 
00037   class MutexBase
00038   {
00039   public:
00040     void Initialize ()
00041     {
00042       pthread_mutex_init (&mutex, 0);
00043       isLocked = false;
00044     }
00045 
00046     void Destroy ()
00047     {
00048       pthread_mutex_destroy (&mutex);
00049     }
00050     
00051     bool IsLocked ()
00052     {
00053       return isLocked;
00054     }
00055 
00056     bool Lock ()
00057     {
00058       int status = pthread_mutex_lock (&mutex);
00059       isLocked = (status == 0);
00060       return isLocked;
00061     }
00062 
00063     bool TryLock ()
00064     {
00065       int status = pthread_mutex_trylock (&mutex);
00066       isLocked = (status == 0);
00067       return isLocked;
00068     }
00069 
00070     void Unlock ()
00071     {
00072       pthread_mutex_unlock (&mutex);
00073     }
00074 
00075   protected:
00076     friend class ConditionBase;
00077 
00078     pthread_mutex_t mutex;
00079     bool isLocked;
00080   };
00081 
00082 
00086 #ifdef CS_PTHREAD_MUTEX_RECURSIVE
00087   class RecursiveMutexBase : public MutexBase
00088   {
00089   public:
00090     void Initialize ()
00091     {
00092       // Use different initialization
00093       pthread_mutexattr_t attr;
00094       pthread_mutexattr_init (&attr);
00095       pthread_mutexattr_settype (&attr, CS_PTHREAD_MUTEX_RECURSIVE);
00096       pthread_mutex_init (&mutex, &attr);
00097     }
00098   }; 
00099 #else
00100   
00101   // Recursive mutex when native recursive mutex isn't supported by pthread
00102   // Emulate it
00103   class RecursiveMutexBase : public MutexBase
00104   {
00105   public:
00106     void Initialize ()
00107     {
00108       MutexBase::Initialize ();
00109 
00110       recursionCount = 0;
00111       validID = false;
00112       pthread_cond_init (&unlockedCond, 0);
00113     }
00114 
00115     void Destroy ()
00116     {
00117       MutexBase::Destroy ();
00118       pthread_cond_destroy (&unlockedCond);
00119     }
00120 
00121     bool IsLocked ()
00122     {
00123       bool ret = false;
00124       MutexBase::Lock ();
00125       
00126       if (validID && recursionCount > 0)
00127       {
00128         ret = true;
00129       }
00130 
00131       MutexBase::Unlock ();
00132       return ret;
00133     }
00134 
00135     bool Lock ()
00136     {
00137       MutexBase::Lock ();
00138 
00139       pthread_t tid = pthread_self ();
00140       if (validID && pthread_equal (threadID, tid))
00141       {
00142         ++recursionCount;
00143       }
00144       else
00145       {
00146         while (validID)
00147         {
00148           pthread_cond_wait (&unlockedCond, &mutex);
00149         }
00150 
00151         threadID = tid;
00152         validID = true;
00153         recursionCount = 1;
00154       }
00155 
00156       MutexBase::Unlock ();
00157     }
00158 
00159     bool TryLock ()
00160     {
00161       bool ret = false;
00162       MutexBase::Lock ();
00163 
00164       pthread_t tid = pthread_self ();
00165       if (validID && pthread_equal (threadID, tid))
00166       {
00167         ++recursionCount;
00168         ret = true;
00169       }
00170       else if (!validID)
00171       {
00172         threadID = tid;
00173         validID = true;
00174         recursionCount = 1;
00175         ret = true;
00176       }
00177 
00178       MutexBase::Unlock ();
00179       return ret;
00180     }
00181 
00182     void Unlock ()
00183     {
00184       MutexBase::Lock ();
00185       pthread_t tid = pthread_self ();
00186       if (validID && !pthread_equal (threadID, tid))
00187       {
00188         MutexBase::Unlock ();
00189         return;
00190       }
00191 
00192       if (--recursionCount == 0)
00193       {
00194         validID = false;
00195         pthread_cond_signal (&unlockedCond);
00196       }
00197 
00198       MutexBase::Unlock ();
00199     }
00200 
00201   protected:
00202     pthread_cond_t unlockedCond;
00203     pthread_t threadID;
00204     int32 recursionCount;
00205     bool validID;
00206   };
00207 
00208 #endif
00209 
00210 } // namespace Implementation
00211 } // namespace Threading
00212 } // namespace CS
00213 
00214 #endif // DOXYGEN_RUN
00215 
00216 #endif // __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__

Generated for Crystal Space 1.2.1 by doxygen 1.5.3