csutil/threading/pthread_mutex.h Source File (Crystal Space 2.0 Public API Reference)

| ## Public API Reference

- Main Page
- Related Pages
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

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     }
    00044
    00045     void Destroy ()
    00046     {
    00047       pthread_mutex_destroy (&mutex);
    00048     }
    00049
    00050     bool Lock ()
    00051     {
    00052       int status = pthread_mutex_lock (&mutex);
    00053       return status == 0;
    00054     }
    00055
    00056     bool TryLock ()
    00057     {
    00058       int status = pthread_mutex_trylock (&mutex);
    00059       return status == 0;
    00060     }
    00061
    00062     void Unlock ()
    00063     {
    00064       pthread_mutex_unlock (&mutex);
    00065     }
    00066
    00067   protected:
    00068     friend class ConditionBase;
    00069
    00070     pthread_mutex_t mutex;
    00071   };
    00072
    00073
    00077 #ifdef CS_PTHREAD_MUTEX_RECURSIVE
    00078   class RecursiveMutexBase : public MutexBase
    00079   {
    00080   public:
    00081     void Initialize ()
    00082     {
    00083       // Use different initialization
    00084       pthread_mutexattr_t attr;
    00085       pthread_mutexattr_init (&attr);
    00086       pthread_mutexattr_settype (&attr, CS_PTHREAD_MUTEX_RECURSIVE);
    00087       pthread_mutex_init (&mutex, &attr);
    00088     }
    00089   };
    00090 #else
    00091
    00092   // Recursive mutex when native recursive mutex isn't supported by pthread
    00093   // Emulate it
    00094   class RecursiveMutexBase : public MutexBase
    00095   {
    00096   public:
    00097     void Initialize ()
    00098     {
    00099       MutexBase::Initialize ();
    00100
    00101       recursionCount = 0;
    00102       validID = false;
    00103       pthread_cond_init (&unlockedCond, 0);
    00104     }
    00105
    00106     void Destroy ()
    00107     {
    00108       MutexBase::Destroy ();
    00109       pthread_cond_destroy (&unlockedCond);
    00110     }
    00111
    00112     bool Lock ()
    00113     {
    00114       MutexBase::Lock ();
    00115
    00116       pthread_t tid = pthread_self ();
    00117       if (validID && pthread_equal (threadID, tid))
    00118       {
    00119         ++recursionCount;
    00120       }
    00121       else
    00122       {
    00123         while (validID)
    00124         {
    00125           pthread_cond_wait (&unlockedCond, &mutex);
    00126         }
    00127
    00128         threadID = tid;
    00129         validID = true;
    00130         recursionCount = 1;
    00131       }
    00132
    00133       MutexBase::Unlock ();
    00134     }
    00135
    00136     bool TryLock ()
    00137     {
    00138       bool ret = false;
    00139       MutexBase::Lock ();
    00140
    00141       pthread_t tid = pthread_self ();
    00142       if (validID && pthread_equal (threadID, tid))
    00143       {
    00144         ++recursionCount;
    00145         ret = true;
    00146       }
    00147       else if (!validID)
    00148       {
    00149         threadID = tid;
    00150         validID = true;
    00151         recursionCount = 1;
    00152         ret = true;
    00153       }
    00154
    00155       MutexBase::Unlock ();
    00156       return ret;
    00157     }
    00158
    00159     void Unlock ()
    00160     {
    00161       MutexBase::Lock ();
    00162       pthread_t tid = pthread_self ();
    00163       if (validID && !pthread_equal (threadID, tid))
    00164       {
    00165         MutexBase::Unlock ();
    00166         return;
    00167       }
    00168
    00169       if (--recursionCount == 0)
    00170       {
    00171         validID = false;
    00172         pthread_cond_signal (&unlockedCond);
    00173       }
    00174
    00175       MutexBase::Unlock ();
    00176     }
    00177
    00178   protected:
    00179     pthread_cond_t unlockedCond;
    00180     pthread_t threadID;
    00181     int32 recursionCount;
    00182     bool validID;
    00183   };
    00184
    00185 #endif
    00186
    00187 } // namespace Implementation
    00188 } // namespace Threading
    00189 } // namespace CS
    00190
    00191 #endif // DOXYGEN_RUN
    00192
    00193 #endif // __CS_CSUTIL_THREADING_PTHREAD_MUTEX_H__