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_PROCESS_MUTEX
00048 #define UNIXSTL_INCL_UNIXSTL_SYNCH_HPP_PROCESS_MUTEX
00049 
00050 #ifndef STLSOFT_DOCUMENTATION_SKIP_SECTION
00051 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_PROCESS_MUTEX_MAJOR      4
00052 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_PROCESS_MUTEX_MINOR      6
00053 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_PROCESS_MUTEX_REVISION   3
00054 # define UNIXSTL_VER_UNIXSTL_SYNCH_HPP_PROCESS_MUTEX_EDIT       73
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/process_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 process_mutex
00128     : public stlsoft_ns_qual(critical_section)< STLSOFT_CRITICAL_SECTION_ISNOT_RECURSIVE
00129                                             ,   STLSOFT_CRITICAL_SECTION_IS_TRYABLE
00130                                             >
00131 {
00134 public:
00135     typedef process_mutex       class_type;
00136     typedef us_bool_t           bool_type;
00137 
00138     typedef pthread_mutex_t*    resource_type;
00140 
00143 public:
00151     process_mutex()
00152         : m_mx(&m_mx_)
00153 #if defined(_POSIX_THREAD_PROCESS_SHARED)
00154         , m_error(create_(&m_mx_, PTHREAD_PROCESS_PRIVATE, true))
00155 #else 
00156         , m_error(create_(&m_mx_, 0, true))
00157 #endif 
00158         , m_bOwnHandle(true)
00159     {}
00160 
00165     process_mutex(pthread_mutex_t* mx, bool_type bTakeOwnership)
00166         : m_mx(mx)
00167         , m_error(0)
00168         , m_bOwnHandle(bTakeOwnership)
00169     {
00170         UNIXSTL_ASSERT(NULL != mx);
00171     }
00172 
00177     ss_explicit_k process_mutex(bool_type bRecursive)
00178         : m_mx(&m_mx_)
00179 #if defined(_POSIX_THREAD_PROCESS_SHARED)
00180         , m_error(create_(&m_mx_, PTHREAD_PROCESS_PRIVATE, bRecursive))
00181 #else 
00182         , m_error(create_(&m_mx_, 0, bRecursive))
00183 #endif 
00184         , m_bOwnHandle(true)
00185     {}
00186 #if defined(_POSIX_THREAD_PROCESS_SHARED)
00192     process_mutex(int pshared, bool_type bRecursive)
00193         : m_mx(&m_mx_)
00194         , m_error(create_(&m_mx_, pshared, bRecursive))
00195         , m_bOwnHandle(true)
00196     {}
00197 #endif 
00199     ~process_mutex() stlsoft_throw_0()
00200     {
00201         if( 0 == m_error &&
00202             m_bOwnHandle)
00203         {
00204             ::pthread_mutex_destroy(m_mx);
00205         }
00206     }
00208 
00211 public:
00218     void lock()
00219     {
00220         m_error = ::pthread_mutex_lock(m_mx);
00221 
00222 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00223         if(0 != m_error)
00224         {
00225             STLSOFT_THROW_X(synchronisation_exception("Mutex lock failed", m_error));
00226         }
00227 #endif 
00228     }
00238     bool try_lock()
00239     {
00240         m_error = ::pthread_mutex_trylock(m_mx);
00241 
00242         if(0 == m_error)
00243         {
00244             return true;
00245         }
00246         else
00247         {
00248 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00249             if(EBUSY != m_error)
00250             {
00251                 STLSOFT_THROW_X(synchronisation_exception("Mutex try-lock failed", m_error));
00252             }
00253 #endif 
00254 
00255             return false;
00256         }
00257     }
00264     void unlock()
00265     {
00266         m_error = ::pthread_mutex_unlock(m_mx);
00267 
00268 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00269         if(0 != m_error)
00270         {
00271             STLSOFT_THROW_X(synchronisation_exception("Mutex unlock failed", m_error));
00272         }
00273 #endif 
00274     }
00275 
00277     int get_error() const stlsoft_throw_0()
00278     {
00279         return m_error;
00280     }
00282 
00285 public:
00287     pthread_mutex_t* handle() stlsoft_throw_0()
00288     {
00289         return m_mx;
00290     }
00292     pthread_mutex_t* get() stlsoft_throw_0()
00293     {
00294         return m_mx;
00295     }
00297 
00300 private:
00301 #if defined(STLSOFT_COMPILER_IS_SUNPRO)
00302     static int pthread_mutexattr_destroy(pthread_mutexattr_t *attr)
00303     {
00304         return ::pthread_mutexattr_destroy(attr);
00305     }
00306 #endif 
00307     static int create_(pthread_mutex_t* mx, int pshared, bool_type bRecursive)
00308     {
00309         pthread_mutexattr_t attr;
00310         int                 res = 0;
00311 
00312         if(0 == (res = ::pthread_mutexattr_init(&attr)))
00313         {
00314             stlsoft::scoped_handle<pthread_mutexattr_t*>    attr_(&attr, pthread_mutexattr_destroy);
00315 
00316             if( !bRecursive ||
00317                 0 == (res = ::pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE)))
00318             {
00319 #if defined(_POSIX_THREAD_PROCESS_SHARED)
00320                 if(0 != (res = ::pthread_mutexattr_setpshared(&attr, pshared)))
00321                 {
00322 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00323                     STLSOFT_THROW_X(synchronisation_exception("Failed to set process-sharing attribute for PTHREADS mutex", res));
00324 #endif 
00325                 }
00326                 else
00327 #else 
00328                 STLSOFT_SUPPRESS_UNUSED(pshared);
00329 #endif 
00330                 {
00331                     if(0 == (res = ::pthread_mutex_init(mx, &attr)))
00332                     {
00333                     }
00334 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00335                     else
00336                     {
00337                         STLSOFT_THROW_X(synchronisation_exception("Failed to set initialise PTHREADS mutex", res));
00338                     }
00339 #endif 
00340                 }
00341             }
00342 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00343             else
00344             {
00345                 STLSOFT_THROW_X(synchronisation_exception("Failed to set recursive attribute to PTHREADS mutex", res));
00346             }
00347 #endif 
00348         }
00349 #ifdef STLSOFT_CF_EXCEPTION_SUPPORT
00350         else
00351         {
00352             STLSOFT_THROW_X(synchronisation_exception("Failed to initialise PTHREADS mutex attributes", res));
00353         }
00354 #endif 
00355 
00356         return res;
00357     }
00359 
00362 private:
00363     pthread_mutex_t         m_mx_;          
00364     pthread_mutex_t* const  m_mx;           
00365     int                     m_error;        
00366     const bool_type         m_bOwnHandle;   
00368 
00371 private:
00372     process_mutex(class_type const& rhs);
00373     process_mutex& operator =(class_type const& rhs);
00375 };
00376 
00377 
00378 
00379 
00380 
00381 #ifndef _UNIXSTL_NO_NAMESPACE
00382 # if defined(_STLSOFT_NO_NAMESPACE) || \
00383      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00384 } 
00385 # else
00386 } 
00387 # endif 
00388 #endif 
00389 
00396 inline void lock_instance(unixstl_ns_qual(process_mutex) &mx)
00397 {
00398     mx.lock();
00399 }
00400 
00407 inline void unlock_instance(unixstl_ns_qual(process_mutex) &mx)
00408 {
00409     mx.unlock();
00410 }
00411 
00412 
00413 #ifndef _UNIXSTL_NO_NAMESPACE
00414 # if defined(_STLSOFT_NO_NAMESPACE) || \
00415      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00416 namespace unixstl
00417 {
00418 # else 
00419 namespace unixstl_project
00420 {
00421 # endif 
00422 #endif 
00423 
00424 
00425 
00426 
00427 
00428 
00433 struct process_mutex_lock_traits
00434 {
00435 public:
00437     typedef process_mutex                lock_type;
00438     typedef process_mutex_lock_traits    class_type;
00439 
00440 
00441 public:
00443     static void lock(process_mutex &c)
00444     {
00445 #if defined(STLSOFT_COMPILER_IS_BORLAND)
00446         
00447         
00448         stlsoft_ns_qual(lock_instance)(c);
00449 #else 
00450         lock_instance(c);
00451 #endif 
00452     }
00453 
00455     static void unlock(process_mutex &c)
00456     {
00457 #if defined(STLSOFT_COMPILER_IS_BORLAND)
00458         
00459         
00460         stlsoft_ns_qual(unlock_instance)(c);
00461 #else 
00462         unlock_instance(c);
00463 #endif 
00464     }
00465 };
00466 
00468 
00469 
00470 #ifdef STLSOFT_UNITTEST
00471 # include "./unittest/process_mutex_unittest_.h"
00472 #endif 
00473 
00474 
00475 
00476 #ifndef _UNIXSTL_NO_NAMESPACE
00477 # if defined(_STLSOFT_NO_NAMESPACE) || \
00478      defined(STLSOFT_DOCUMENTATION_SKIP_SECTION)
00479 } 
00480 # else
00481 } 
00482 } 
00483 # endif 
00484 #endif 
00485 
00486 
00487 
00488 #endif 
00489 
00490