#pragma once /** @file @brief mutex @author MITSUNARI Shigeo(@herumi) @author MITSUNARI Shigeo */ #ifdef _WIN32 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include #else #include #include #endif #include #include namespace cybozu { class ConditionVariable; namespace thread { #ifdef _WIN32 typedef HANDLE MutexHandle; inline void MutexInit(MutexHandle& mutex) { // mutex = CreateSemaphore(NULL /* no security */, 1 /* init */, 0x7FFFFFFF /* max */, NULL /* no name */); mutex = CreateMutex(NULL /* no security */, FALSE /* no owner */, NULL /* no name */); } inline void MutexLock(MutexHandle& mutex) { WaitForSingleObject(mutex, INFINITE); } /* return false if timeout @param msec [in] msec */ inline bool MutexLockTimeout(MutexHandle& mutex, int msec) { DWORD ret = WaitForSingleObject(mutex, msec); if (ret == WAIT_OBJECT_0) { return true; } if (ret == WAIT_TIMEOUT) { return false; } /* ret == WAIT_ABANDONED */ assert(0); return false; } inline void MutexUnlock(MutexHandle& mutex) { // ReleaseSemaphore(mutex, 1, NULL); ReleaseMutex(mutex); } inline void MutexTerm(MutexHandle& mutex) { CloseHandle(mutex); } #else typedef pthread_mutex_t MutexHandle; inline void MutexInit(MutexHandle& mutex) { #if 1 pthread_mutex_init(&mutex, NULL); #else pthread_mutexattr_t attr; pthread_mutexattr_init(&attr); if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_TIMED_NP)) { perror("pthread_mutexattr_settype"); exit(1); } pthread_mutex_init(&mutex, &attr); pthread_mutexattr_destroy(&attr); #endif } inline void MutexLock(MutexHandle& mutex) { pthread_mutex_lock(&mutex); } #if 0 inline bool MutexLockTimeout(MutexHandle& mutex, int msec) { timespec absTime; clock_gettime(CLOCK_REALTIME, &absTime); absTime.tv_sec += msec / 1000; absTime.tv_nsec += msec % 1000; bool ret = pthread_mutex_timedlock(&mutex, &absTime) == 0; return ret; } #endif inline void MutexUnlock(MutexHandle& mutex) { pthread_mutex_unlock(&mutex); } inline void MutexTerm(MutexHandle& mutex) { pthread_mutex_destroy(&mutex); } #endif template class AutoLockT { public: explicit AutoLockT(T &t) : t_(t) { t_.lock(); } ~AutoLockT() { t_.unlock(); } private: T& t_; AutoLockT& operator=(const AutoLockT&); }; } // cybozu::thread class Mutex { friend class cybozu::ConditionVariable; public: Mutex() { thread::MutexInit(hdl_); } ~Mutex() { thread::MutexTerm(hdl_); } void lock() { thread::MutexLock(hdl_); } #if 0 bool lockTimeout(int msec) { return thread::MutexLockTimeout(hdl_, msec); } #endif void unlock() { thread::MutexUnlock(hdl_); } private: Mutex(const Mutex&); Mutex& operator=(const Mutex&); thread::MutexHandle hdl_; }; typedef cybozu::thread::AutoLockT AutoLock; } // cybozu