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 #include "base/primitives.h"
00028
00029 BEGIN_TERIMBER_NAMESPACE
00030 #pragma pack(4)
00031
00032 #if OS_TYPE != OS_WIN32
00033
00034 static
00035 void
00036 calculate_absolute_time_by_timeout(size_t tm_relative, timespec& tm_absolute)
00037 {
00038
00039 timeval now_;
00040 gettimeofday(&now_, 0);
00041
00042 tm_absolute.tv_sec = now_.tv_sec + (unsigned long)tm_relative / 1000;
00043 tm_absolute.tv_nsec = now_.tv_usec * 1000 + ((unsigned long)tm_relative % 1000) * 1000000;
00044
00045 if (tm_absolute.tv_nsec >= 1000000000)
00046 {
00047 ++tm_absolute.tv_sec;
00048 tm_absolute.tv_nsec -= 1000000000;
00049 }
00050 }
00051
00052 #endif
00054 // constructor
00055 mutex::mutex()
00056 {
00057 #if OS_TYPE == OS_WIN32
00058 InitializeCriticalSection(&_handle);
00059 #else
00060 pthread_mutexattr_t attr;
00061 pthread_mutexattr_init(&attr);
00062 pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
00063 pthread_mutex_init(&_handle, &attr);
00064 #endif
00065 }
00066
00067
00068 mutex::~mutex()
00069 {
00070 #if OS_TYPE == OS_WIN32
00071 DeleteCriticalSection(&_handle);
00072 #else
00073 pthread_mutex_destroy(&_handle);
00074 #endif
00075 }
00076
00077
00078 bool
00079 mutex::lock() const
00080 {
00081 #if OS_TYPE == OS_WIN32
00082 EnterCriticalSection(&_handle);
00083 return true;
00084 #else
00085 return !pthread_mutex_lock(&_handle);
00086 #endif
00087 }
00088
00089
00090
00091 void
00092 mutex::unlock() const
00093 {
00094 #if OS_TYPE == OS_WIN32
00095 LeaveCriticalSection(&_handle);
00096 #else
00097 pthread_mutex_unlock(&_handle);
00098 #endif
00099 }
00100
00101
00102 bool
00103 mutex::trylock() const
00104 {
00105 #if OS_TYPE == OS_WIN32
00106 return TRUE == TryEnterCriticalSection(&_handle);
00107 #else
00108 return !pthread_mutex_trylock(&_handle);
00109 #endif
00110 }
00111
00113
00114 event::event(bool manual_reset, bool init_state)
00115 {
00116 #if OS_TYPE == OS_WIN32
00117
00118 _handle = CreateEvent(0, manual_reset, init_state, 0);
00119 #else
00120 _handle._cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
00121
00122 pthread_cond_init(_handle._cond, 0);
00123
00124 _handle._manual_reset = manual_reset;
00125 _handle._signaled = init_state;
00126 #endif
00127 }
00128
00129
00130 event::~event()
00131 {
00132 #if OS_TYPE == OS_WIN32
00133
00134 CloseHandle(_handle);
00135 #else
00136
00137 pthread_cond_destroy(_handle._cond);
00138 free(_handle._cond);
00139 #endif
00140 }
00141
00142
00143
00144 void
00145 event::signal() const
00146 {
00147 #if OS_TYPE == OS_WIN32
00148
00149 SetEvent(_handle);
00150 #else
00151
00152 mutex_keeper keeper(_handle._mtx);
00153
00154 _handle._manual_reset ?
00155 pthread_cond_broadcast(_handle._cond) :
00156 pthread_cond_signal(_handle._cond);
00157
00158
00159 _handle._signaled = true;
00160 #endif
00161 }
00162
00163
00164 void
00165 event::nonsignal() const
00166 {
00167 #if OS_TYPE == OS_WIN32
00168
00169 ResetEvent(_handle);
00170 #else
00171 mutex_keeper keeper(_handle._mtx);
00172 _handle._signaled = false;
00173 #endif
00174 }
00175
00176
00177
00178 size_t
00179 event::wait(size_t timeout) const
00180 {
00181 #if OS_TYPE == OS_WIN32
00182
00183 return WaitForSingleObject(_handle, (DWORD)timeout);
00184 #else
00185
00186 mutex_keeper keeper(_handle._mtx);
00187
00188 size_t ret = 0;
00189
00190 if (!_handle._signaled)
00191 {
00192 if (!timeout)
00193 return WAIT_TIMEOUT;
00194 else
00195 {
00196 timespec timeout_;
00197 if (INFINITE != timeout)
00198 {
00199
00200 calculate_absolute_time_by_timeout(timeout, timeout_);
00201 }
00202
00203
00204 do
00205 {
00206 ret = (INFINITE == timeout ? pthread_cond_wait(_handle._cond, _handle._mtx) :
00207 pthread_cond_timedwait(_handle._cond, _handle._mtx, &timeout_));
00208 }
00209 while (!ret && !_handle._signaled);
00210 }
00211 }
00212
00213
00214 switch (ret)
00215 {
00216 case 0:
00217 if (!_handle._manual_reset)
00218 _handle._signaled = false;
00219
00220 return WAIT_OBJECT_0;
00221
00222 case ETIMEDOUT:
00223 default:
00224 return WAIT_TIMEOUT;
00225 }
00226 #endif
00227 }
00228
00230
00231 semaphore::semaphore(size_t initial_count, size_t max_count)
00232 {
00233
00234 assert(max_count != 0);
00235 assert(initial_count <= max_count);
00236
00237 #if OS_TYPE == OS_WIN32
00238
00239 _handle = CreateSemaphore(0, (LONG)initial_count, (LONG)max_count, 0);
00240 #else
00241 _handle._cond = (pthread_cond_t*)malloc(sizeof(pthread_cond_t));
00242
00243 pthread_cond_init(_handle._cond, 0);
00244 _handle._max_count = max_count;
00245 _handle._init_count = initial_count;
00246 #endif
00247 }
00248
00249
00250 semaphore::~semaphore()
00251 {
00252 #if OS_TYPE == OS_WIN32
00253
00254 CloseHandle(_handle);
00255 #else
00256
00257 pthread_cond_destroy(_handle._cond);
00258 free(_handle._cond);
00259 #endif
00260 }
00261
00262
00263
00264 bool
00265 semaphore::release(size_t count) const
00266 {
00267 if (!count)
00268 return false;
00269
00270 #if OS_TYPE == OS_WIN32
00271
00272 return TRUE == ReleaseSemaphore(_handle, (LONG)count, 0);
00273 #else
00274
00275 mutex_keeper keeper(_handle._mtx);
00276
00277 if (_handle._init_count >= _handle._max_count)
00278 return false;
00279
00280 if (_handle._init_count + count > _handle._max_count)
00281 _handle._init_count = _handle._max_count;
00282 else
00283 _handle._init_count += count;
00284
00285
00286 count == 1 ?
00287 pthread_cond_signal(_handle._cond) :
00288 pthread_cond_broadcast(_handle._cond);
00289
00290 return true;
00291 #endif
00292 }
00293
00294
00295
00296 size_t
00297 semaphore::wait(size_t timeout) const
00298 {
00299 #if OS_TYPE == OS_WIN32
00300
00301 return WaitForSingleObject(_handle, (DWORD)timeout);
00302 #else
00303 mutex_keeper keeper(_handle._mtx);
00304
00305 size_t ret = 0;
00306
00307 if (!_handle._init_count)
00308 {
00309 if (!timeout)
00310 return WAIT_TIMEOUT;
00311 else
00312 {
00313 timespec timeout_;
00314 if (INFINITE != timeout)
00315 {
00316
00317 calculate_absolute_time_by_timeout(timeout, timeout_);
00318 }
00319
00320
00321 do
00322 {
00323 ret = (INFINITE == timeout ? pthread_cond_wait(_handle._cond, _handle._mtx) :
00324 pthread_cond_timedwait(_handle._cond, _handle._mtx, &timeout_));
00325 }
00326 while (!ret && !_handle._init_count);
00327 }
00328 }
00329
00330
00331 switch (ret)
00332 {
00333 case 0:
00334 --_handle._init_count;
00335 return WAIT_OBJECT_0;
00336
00337 case ETIMEDOUT:
00338 default:
00339 return WAIT_TIMEOUT;
00340 }
00341 #endif
00342 }
00343
00344
00345 #pragma pack()
00346 END_TERIMBER_NAMESPACE