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 #include "Poco/Mutex_POSIX.h"
00038 #include "Poco/Timestamp.h"
00039 #if !defined(POCO_NO_SYS_SELECT_H)
00040 #include <sys/select.h>
00041 #endif
00042 #include <unistd.h>
00043 #include <sys/time.h>
00044
00045
00046 #if defined(_POSIX_TIMEOUTS) && (_POSIX_TIMEOUTS - 200112L) >= 0L
00047 #if defined(_POSIX_THREADS) && (_POSIX_THREADS - 200112L) >= 0L
00048 #define POCO_HAVE_MUTEX_TIMEOUT
00049 #endif
00050 #endif
00051
00052
00053 namespace Poco {
00054
00055
00056 MutexImpl::MutexImpl()
00057 {
00058 pthread_mutexattr_t attr;
00059 pthread_mutexattr_init(&attr);
00060 #if defined(PTHREAD_MUTEX_RECURSIVE_NP)
00061 pthread_mutexattr_settype_np(&attr, PTHREAD_MUTEX_RECURSIVE_NP);
00062 #else
00063 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00064 #endif
00065 if (pthread_mutex_init(&_mutex, &attr))
00066 {
00067 pthread_mutexattr_destroy(&attr);
00068 throw SystemException("cannot create mutex");
00069 }
00070 pthread_mutexattr_destroy(&attr);
00071 }
00072
00073
00074 MutexImpl::MutexImpl(bool fast)
00075 {
00076 pthread_mutexattr_t attr;
00077 pthread_mutexattr_init(&attr);
00078 #if defined(PTHREAD_MUTEX_RECURSIVE_NP)
00079 pthread_mutexattr_settype_np(&attr, fast ? PTHREAD_MUTEX_NORMAL_NP : PTHREAD_MUTEX_RECURSIVE_NP);
00080 #else
00081 pthread_mutexattr_settype(&attr, fast ? PTHREAD_MUTEX_NORMAL : PTHREAD_MUTEX_RECURSIVE);
00082 #endif
00083 if (pthread_mutex_init(&_mutex, &attr))
00084 {
00085 pthread_mutexattr_destroy(&attr);
00086 throw SystemException("cannot create mutex");
00087 }
00088 pthread_mutexattr_destroy(&attr);
00089 }
00090
00091
00092 MutexImpl::~MutexImpl()
00093 {
00094 pthread_mutex_destroy(&_mutex);
00095 }
00096
00097
00098 bool MutexImpl::tryLockImpl(long milliseconds)
00099 {
00100 #if defined(POCO_HAVE_MUTEX_TIMEOUT)
00101 struct timespec abstime;
00102 struct timeval tv;
00103 gettimeofday(&tv, NULL);
00104 abstime.tv_sec = tv.tv_sec + milliseconds / 1000;
00105 abstime.tv_nsec = tv.tv_usec*1000 + (milliseconds % 1000)*1000000;
00106 if (abstime.tv_nsec >= 1000000000)
00107 {
00108 abstime.tv_nsec -= 1000000000;
00109 abstime.tv_sec++;
00110 }
00111 int rc = pthread_mutex_timedlock(&_mutex, &abstime);
00112 if (rc == 0)
00113 return true;
00114 else if (rc == ETIMEDOUT)
00115 return false;
00116 else
00117 throw SystemException("cannot lock mutex");
00118 #else
00119 const int sleepMillis = 5;
00120 Timestamp now;
00121 Timestamp::TimeDiff diff(Timestamp::TimeDiff(milliseconds)*1000);
00122 do
00123 {
00124 int rc = pthread_mutex_trylock(&_mutex);
00125 if (rc == 0)
00126 return true;
00127 else if (rc != EBUSY)
00128 throw SystemException("cannot lock mutex");
00129 struct timeval tv;
00130 tv.tv_sec = 0;
00131 tv.tv_usec = sleepMillis * 1000;
00132 select(0, NULL, NULL, NULL, &tv);
00133 }
00134 while (!now.isElapsed(diff));
00135 return false;
00136 #endif
00137 }
00138
00139
00140 FastMutexImpl::FastMutexImpl(): MutexImpl(true)
00141 {
00142 }
00143
00144
00145 FastMutexImpl::~FastMutexImpl()
00146 {
00147 }
00148
00149
00150 }