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 #include "CSConfig.h"
00029
00030 #include <assert.h>
00031 #ifdef OS_WINDOWS
00032 extern int gettimeofday(struct timeval *tv, struct timezone *tz);
00033 #else
00034 #include <sys/time.h>
00035 #endif
00036
00037 #include <unistd.h>
00038
00039 #include "CSException.h"
00040 #include "CSMutex.h"
00041 #include "CSGlobal.h"
00042 #include "CSLog.h"
00043
00044
00045
00046
00047
00048
00049 CSMutex::CSMutex()
00050 #ifdef DEBUG
00051 :
00052 iLocker(NULL),
00053 trace(false)
00054 #endif
00055 {
00056 int err;
00057
00058 if ((err = pthread_mutex_init(&iMutex, NULL)))
00059 CSException::throwOSError(CS_CONTEXT, err);
00060 }
00061
00062 CSMutex::~CSMutex()
00063 {
00064 pthread_mutex_destroy(&iMutex);
00065 }
00066
00067 void CSMutex::lock()
00068 {
00069 int err = 0;
00070
00071 #ifdef DEBUG
00072 int waiting = 2000;
00073 while (((err = pthread_mutex_trylock(&iMutex)) == EBUSY) && (waiting > 0)) {
00074 usleep(500);
00075 waiting--;
00076 }
00077 if (err) {
00078 if (err == EBUSY) {
00079 CSL.logf(iLocker, CSLog::Protocol, "Thread holding lock.\n");
00080 }
00081
00082 if ((err) || (err = pthread_mutex_lock(&iMutex)))
00083 CSException::throwOSError(CS_CONTEXT, err);
00084 }
00085
00086 iLocker = CSThread::getSelf();
00087 if (trace)
00088 CSL.logf(iLocker, CSLog::Protocol, "Mutex locked\n");
00089 #else
00090 if ((err = pthread_mutex_lock(&iMutex)))
00091 CSException::throwOSError(CS_CONTEXT, err);
00092 #endif
00093 }
00094
00095 void CSMutex::unlock()
00096 {
00097 #ifdef DEBUG
00098 if (trace)
00099 CSL.logf(iLocker, CSLog::Protocol, "Mutex unlocked\n");
00100 iLocker = NULL;
00101 #endif
00102 pthread_mutex_unlock(&iMutex);
00103 }
00104
00105
00106
00107
00108
00109
00110 CSLock::CSLock():
00111 CSMutex(),
00112 iLockingThread(NULL),
00113 iLockCount(0)
00114 {
00115 }
00116
00117 CSLock::~CSLock()
00118 {
00119 }
00120
00121 void CSLock::lock()
00122 {
00123 int err;
00124
00125 enter_();
00126 if (iLockingThread != self) {
00127 if ((err = pthread_mutex_lock(&iMutex)))
00128 CSException::throwOSError(CS_CONTEXT, err);
00129 iLockingThread = self;
00130 }
00131 iLockCount++;
00132 exit_();
00133 }
00134
00135 void CSLock::unlock()
00136 {
00137 enter_();
00138 ASSERT(iLockingThread == self);
00139 if (!(--iLockCount)) {
00140 iLockingThread = NULL;
00141 pthread_mutex_unlock(&iMutex);
00142 }
00143 exit_();
00144 }
00145
00146 bool CSLock::haveLock()
00147 {
00148 enter_();
00149 return_(iLockingThread == self);
00150 }
00151
00152
00153
00154
00155
00156
00157 CSSync::CSSync():
00158 CSLock()
00159 {
00160 int err;
00161
00162 if ((err = pthread_cond_init(&iCondition, NULL)))
00163 CSException::throwOSError(CS_CONTEXT, err);
00164 }
00165
00166 CSSync::~CSSync()
00167 {
00168 pthread_cond_destroy(&iCondition);
00169 }
00170
00171 void CSSync::wait()
00172 {
00173 int err;
00174 int lock_count;
00175
00176 enter_();
00177 ASSERT(iLockingThread == self);
00178 lock_count = iLockCount;
00179 iLockCount = 0;
00180 iLockingThread = NULL;
00181 err = pthread_cond_wait(&iCondition, &iMutex);
00182 iLockCount = lock_count;
00183 iLockingThread = self;
00184 if (err)
00185 CSException::throwOSError(CS_CONTEXT, err);
00186 exit_();
00187 }
00188
00189 void CSSync::wait(time_t milli_sec)
00190 {
00191 struct timespec abstime;
00192 int lock_count;
00193 int err;
00194 uint64_t micro_sec;
00195
00196 enter_();
00197 struct timeval now;
00198
00199
00200 gettimeofday(&now, NULL);
00201 micro_sec = (uint64_t) now.tv_sec * (uint64_t) 1000000 + (uint64_t) now.tv_usec;
00202
00203
00204 micro_sec += (uint64_t) milli_sec * (uint64_t) 1000;
00205
00206
00207 abstime.tv_sec = (long) (micro_sec / 1000000);
00208 abstime.tv_nsec = (long) ((micro_sec % 1000000) * 1000);
00209
00210 ASSERT(iLockingThread == self);
00211 lock_count = iLockCount;
00212 iLockCount = 0;
00213 iLockingThread = NULL;
00214 err = pthread_cond_timedwait(&iCondition, &iMutex, &abstime);
00215 iLockCount = lock_count;
00216 iLockingThread = self;
00217 if (err && err != ETIMEDOUT)
00218 CSException::throwOSError(CS_CONTEXT, err);
00219 exit_();
00220 }
00221
00222 void CSSync::wakeup()
00223 {
00224 int err;
00225
00226 if ((err = pthread_cond_broadcast(&iCondition)))
00227 CSException::throwOSError(CS_CONTEXT, err);
00228 }
00229
00230
00231