00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 
00037 
00038 
00039 
00040 
00047 #ifndef UNIXSTL_INCL_UNIXSTL_SYNCH_HPP_THREAD_MUTEX
00048 #define UNIXSTL_INCL_UNIXSTL_SYNCH_HPP_THREAD_MUTEX
00049 
00050 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00051 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_THREAD_MUTEX_MAJOR       4
00052 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_THREAD_MUTEX_MINOR       3
00053 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_THREAD_MUTEX_REVISION    3
00054 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_THREAD_MUTEX_EDIT        56
00055 #endif 
00056 
00057 
00058 
00059 
00060 
00061 #ifndef UNIXSTL_INCL_UNIXSTL_H_UNIXSTL
00062 # include <unixstl/unixstl.h>
00063 #endif 
00064 #ifndef UNIXSTL_INCL_UNIXSTL_SYNCH_UTIL_H_FEATURES
00065 # include <unixstl/synch/util/features.h>
00066 #endif 
00067 #ifndef UNIXSTL_USING_PTHREADS
00068 # error unixstl/synch/thread_mutex.hpp cannot be included in non-multithreaded compilation. _REENTRANT and/or _POSIX_THREADS must be defined
00069 #endif 
00070 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00071 # ifndef UNIXSTL_INCL_UNIXSTL_SYNCH_ERROR_HPP_EXCEPTIONS
00072 #  include <unixstl/synch/error/exceptions.hpp>
00073 # endif 
00074 #endif 
00075 #ifndef STLSOFT_INCL_STLSOFT_SMARTPTR_HPP_SCOPED_HANDLE
00076 # include <stlsoft/smartptr/scoped_handle.hpp>
00077 #endif 
00078 #ifndef STLSOFT_INCL_STLSOFT_SYNCH_HPP_CONCEPTS
00079 # include <stlsoft/synch/concepts.hpp>
00080 #endif 
00081 
00082 #ifndef STLSOFT_INCL_H_ERRNO
00083 # define STLSOFT_INCL_H_ERRNO
00084 # include <errno.h>
00085 #endif 
00086 #ifndef STLSOFT_INCL_H_PTHREAD
00087 # define STLSOFT_INCL_H_PTHREAD
00088 # include <pthread.h>
00089 #endif 
00090 
00091 #ifdef STLSOFT_UNITTEST
00092 # include <stdio.h>
00093 #endif 
00094 
00095 
00096 
00097 
00098 
00099 #ifndef _UNIXSTL_NO_NAMESPACE
00100 # if defined(_STLSOFT_NO_NAMESPACE) || \
00101      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00102 
00103 namespace unixstl
00104 {
00105 # else
00106 
00107 
00108 namespace stlsoft
00109 {
00110 
00111 namespace unixstl_project
00112 {
00113 
00114 # endif 
00115 #endif 
00116 
00117 
00118 
00119 
00120 
00121 
00127 class thread_mutex
00128     : public stlsoft_ns_qual(critical_section)< STLSOFT_CRITICAL_SECTION_IS_RECURSIVE
00129                                             ,   STLSOFT_CRITICAL_SECTION_IS_TRYABLE
00130                                             >
00131 {
00134 public:
00135     typedef thread_mutex        class_type;
00136     typedef us_bool_t           bool_type;
00137 
00138     typedef pthread_mutex_t*    resource_type;
00140 
00143 public:
00145     ss_explicit_k thread_mutex(bool_type bRecursive = true) stlsoft_throw_0()
00146         : m_mx(&m_mx_)
00147         , m_error(create_(&m_mx_, bRecursive))
00148         , m_bOwnHandle(true)
00149     {}
00150 
00155     thread_mutex(pthread_mutex_t* mx, bool_type bTakeOwnership)
00156         : m_mx(mx)
00157         , m_error(0)
00158         , m_bOwnHandle(bTakeOwnership)
00159     {
00160         UNIXSTL_ASSERT(NULL != mx);
00161     }
00162 
00164     ~thread_mutex() stlsoft_throw_0()
00165     {
00166         if( 0 == m_error &&
00167             m_bOwnHandle)
00168         {
00169             ::pthread_mutex_destroy(m_mx);
00170         }
00171     }
00173 
00176 public:
00183     void lock()
00184     {
00185         m_error = ::pthread_mutex_lock(m_mx);
00186 
00187 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00188         if(0 != m_error)
00189         {
00190             STLSOFT_THROW_X(synchronisation_exception("Mutex lock failed", m_error));
00191         }
00192 #endif 
00193     }
00203     bool try_lock()
00204     {
00205         m_error = ::pthread_mutex_trylock(m_mx);
00206 
00207         if(0 == m_error)
00208         {
00209             return true;
00210         }
00211         else
00212         {
00213 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00214             if(EBUSY != m_error)
00215             {
00216                 STLSOFT_THROW_X(synchronisation_exception("Mutex try-lock failed", m_error));
00217             }
00218 #endif 
00219 
00220             return false;
00221         }
00222     }
00229     void unlock() stlsoft_throw_0()
00230     {
00231         m_error = ::pthread_mutex_unlock(m_mx);
00232 
00233 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00234         if(0 != m_error)
00235         {
00236             STLSOFT_THROW_X(synchronisation_exception("Mutex unlock failed", m_error));
00237         }
00238 #endif 
00239     }
00240 
00242     int get_error() const stlsoft_throw_0()
00243     {
00244         return m_error;
00245     }
00247 
00250 public:
00252     pthread_mutex_t* handle() stlsoft_throw_0()
00253     {
00254         return m_mx;
00255     }
00257     pthread_mutex_t* get() stlsoft_throw_0()
00258     {
00259         return m_mx;
00260     }
00262 
00265 private:
00266 #if defined(STLSOFT_COMPILER_IS_SUNPRO)
00267     static int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
00268     {
00269         return ::pthread_mutexattr_destroy(attr);
00270     }
00271 #endif 
00272     static int create_(pthread_mutex_t* mx, bool_type bRecursive)
00273     {
00274         pthread_mutexattr_t attr;
00275         int                 res = 0;
00276 
00277         if(0 == (res = ::pthread_mutexattr_init(&attr)))
00278         {
00279             stlsoft::scoped_handle<pthread_mutexattr_t*>    attr_(&attr, pthread_mutexattr_destroy);
00280 
00281             if( !bRecursive ||
00282                 0 == (res = ::pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)))
00283             {
00284                 if(0 == ::pthread_mutex_init(mx, &attr))
00285                 {
00286                 }
00287 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00288                 else
00289                 {
00290                     STLSOFT_THROW_X(synchronisation_exception("Failed to set initialise PTHREADS mutex", res));
00291                 }
00292 #endif 
00293             }
00294 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00295             else
00296             {
00297                 STLSOFT_THROW_X(synchronisation_exception("Failed to set recursive attribute to PTHREADS mutex", res));
00298             }
00299 #endif 
00300         }
00301 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00302         else
00303         {
00304             STLSOFT_THROW_X(synchronisation_exception("Failed to initialise PTHREADS mutex attributes", res));
00305         }
00306 #endif 
00307 
00308         return res;
00309     }
00311 
00314 private:
00315     pthread_mutex_t         m_mx_;          
00316     pthread_mutex_t* const  m_mx;           
00317     int                     m_error;        
00318     const bool_type         m_bOwnHandle;   
00320 
00323 private:
00324     thread_mutex(class_type const& rhs);
00325     thread_mutex& operator =(class_type const& rhs);
00327 };
00328 
00329 
00330 
00331 
00332 
00333 #ifndef _UNIXSTL_NO_NAMESPACE
00334 # if defined(_STLSOFT_NO_NAMESPACE) || \
00335      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00336 } 
00337 # else
00338 } 
00339 # endif 
00340 #endif 
00341 
00348 inline void lock_instance(unixstl_ns_qual(thread_mutex) &mx)
00349 {
00350     mx.lock();
00351 }
00352 
00359 inline void unlock_instance(unixstl_ns_qual(thread_mutex) &mx)
00360 {
00361     mx.unlock();
00362 }
00363 
00364 
00365 
00366 #ifndef _UNIXSTL_NO_NAMESPACE
00367 # if defined(_STLSOFT_NO_NAMESPACE) || \
00368      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00369 namespace unixstl
00370 {
00371 # else
00372 namespace unixstl_project
00373 {
00374 # endif 
00375 #endif 
00376 
00377 
00378 
00379 
00380 
00381 
00386 struct thread_mutex_lock_traits
00387 {
00388 public:
00390     typedef thread_mutex                lock_type;
00391     typedef thread_mutex_lock_traits    class_type;
00392 
00393 
00394 public:
00396     static void lock(thread_mutex &c)
00397     {
00398         lock_instance(c);
00399     }
00400 
00402     static void unlock(thread_mutex &c)
00403     {
00404         unlock_instance(c);
00405     }
00406 };
00407 
00409 
00410 
00411 #ifdef STLSOFT_UNITTEST
00412 # include "./unittest/thread_mutex_unittest_.h"
00413 #endif 
00414 
00415 
00416 
00417 #ifndef _UNIXSTL_NO_NAMESPACE
00418 # if defined(_STLSOFT_NO_NAMESPACE) || \
00419      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00420 } 
00421 # else
00422 } 
00423 } 
00424 # endif 
00425 #endif 
00426 
00427 
00428 
00429 #endif 
00430 
00431