├── Mutex.cpp ├── Mutex.h ├── README.md ├── Semaphore.cpp ├── Semaphore.h ├── Thread.cpp ├── Thread.h └── main.cpp /Mutex.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Mutex.h" 3 | 4 | #ifdef _WIN32 5 | // windows 6 | #include 7 | #else 8 | // linux 9 | #include 10 | #endif 11 | 12 | namespace Wz 13 | { 14 | 15 | struct MutexHandle 16 | { 17 | #ifdef _WIN32 18 | // windows 19 | HANDLE pMutex; 20 | #else 21 | // linux 22 | pthread_mutex_t pMutex; 23 | #endif 24 | }; 25 | 26 | Mutex::Mutex() 27 | { 28 | mutexHandle = new MutexHandle; 29 | #ifdef _WIN32 30 | // windows 31 | mutexHandle->pMutex = CreateMutex(NULL, 32 | true, 33 | NULL); 34 | if (NULL == mutexHandle->pMutex) 35 | { 36 | delete mutexHandle; 37 | mutexHandle = NULL; 38 | printf("Mutex: mutex create failed."); 39 | } 40 | ReleaseMutex(mutexHandle->pMutex); 41 | #else 42 | // linux 43 | if (0 != pthread_mutex_init(&(mutexHandle->pMutex), 44 | NULL)) 45 | { 46 | delete mutexHandle; 47 | mutexHandle = NULL; 48 | printf("Mutex: mutex create failed."); 49 | } 50 | #endif 51 | } 52 | 53 | Mutex::~Mutex() 54 | { 55 | if (NULL != mutexHandle) 56 | { 57 | #ifdef _WIN32 58 | // windows 59 | CloseHandle(mutexHandle->pMutex); 60 | #else 61 | // linux 62 | pthread_mutex_destroy(&(mutexHandle->pMutex)); 63 | #endif 64 | delete mutexHandle; 65 | mutexHandle = NULL; 66 | } 67 | } 68 | 69 | void Mutex::lock() 70 | { 71 | if (NULL == mutexHandle) 72 | { 73 | return; 74 | } 75 | #ifdef _WIN32 76 | // windows 77 | WaitForSingleObject(mutexHandle->pMutex, INFINITE); 78 | #else 79 | // linux 80 | pthread_mutex_lock(&(mutexHandle->pMutex)); 81 | #endif 82 | } 83 | 84 | void Mutex::unlock() 85 | { 86 | if (NULL == mutexHandle) 87 | { 88 | return; 89 | } 90 | #ifdef _WIN32 91 | // windows 92 | ReleaseMutex(mutexHandle->pMutex); 93 | #else 94 | // linux 95 | pthread_mutex_unlock(&(mutexHandle->pMutex)); 96 | #endif 97 | } 98 | 99 | } // namespace Wz -------------------------------------------------------------------------------- /Mutex.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _MUTEX_H_ 3 | #define _MUTEX_H_ 4 | 5 | #include 6 | 7 | namespace Wz 8 | { 9 | 10 | struct MutexHandle; 11 | 12 | class Mutex 13 | { 14 | public: 15 | Mutex(); 16 | ~Mutex(); 17 | 18 | void lock(); 19 | void unlock(); 20 | 21 | private: 22 | MutexHandle *mutexHandle; 23 | }; 24 | 25 | } // namespace Wz 26 | 27 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Thread_Mutex_Semaphore 2 | C++ Cross-Platform Thread , Mutex and Semaphore 3 | 4 | ## Linux Test 5 | ```shell 6 | g++ *.cpp -lpthread -o main 7 | ./main 8 | ``` 9 | 10 | *** 11 | 12 | ## Windows Test 13 | create a visual studio project and copy the source files to test. -------------------------------------------------------------------------------- /Semaphore.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Semaphore.h" 3 | 4 | #ifdef _WIN32 5 | // windows 6 | #include 7 | #else 8 | // linux 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #endif 15 | 16 | namespace Wz 17 | { 18 | 19 | struct SemaphoreHandle 20 | { 21 | #ifdef _WIN32 22 | // windows 23 | HANDLE pSemaphore; 24 | #else 25 | // linux 26 | sem_t pSemaphore; 27 | #endif 28 | }; 29 | 30 | Semaphore::Semaphore(const int &value) 31 | { 32 | semaphoreHandle = new SemaphoreHandle; 33 | #ifdef _WIN32 34 | // windows 35 | semaphoreHandle->pSemaphore = CreateSemaphore(NULL, 36 | value, 37 | 5000, 38 | NULL); 39 | if (NULL == semaphoreHandle->pSemaphore) 40 | #else 41 | // linux 42 | if (0 != sem_init(&(semaphoreHandle->pSemaphore), 43 | 1, 44 | value)) 45 | #endif 46 | { 47 | delete semaphoreHandle; 48 | semaphoreHandle = NULL; 49 | } 50 | } 51 | 52 | Semaphore::~Semaphore() 53 | { 54 | if (NULL != semaphoreHandle) 55 | { 56 | #ifdef _WIN32 57 | // windows 58 | CloseHandle(semaphoreHandle->pSemaphore); 59 | #else 60 | // linux 61 | sem_destroy(&(semaphoreHandle->pSemaphore)); 62 | #endif 63 | delete semaphoreHandle; 64 | semaphoreHandle = NULL; 65 | } 66 | } 67 | 68 | void Semaphore::wait() 69 | { 70 | if (NULL == semaphoreHandle) 71 | { 72 | return; 73 | } 74 | 75 | #ifdef _WIN32 76 | // windows 77 | WaitForSingleObject(semaphoreHandle->pSemaphore, INFINITE); 78 | #else 79 | // linux 80 | sem_wait(&(semaphoreHandle->pSemaphore)); 81 | #endif 82 | } 83 | 84 | bool Semaphore::wait(const unsigned int &ms) 85 | { 86 | if (NULL == semaphoreHandle) 87 | { 88 | return false; 89 | } 90 | 91 | #ifdef _WIN32 92 | // windows 93 | DWORD result = WaitForSingleObject(semaphoreHandle->pSemaphore, ms); 94 | if (result == WAIT_OBJECT_0) 95 | #else 96 | // linux 97 | timeval tv_now; 98 | gettimeofday(&tv_now, NULL); 99 | 100 | timespec ts; 101 | ts.tv_sec = tv_now.tv_sec; 102 | ts.tv_nsec = tv_now.tv_usec * 1000; 103 | 104 | int ns = ts.tv_nsec + (ms % 1000) * 1000000; 105 | ts.tv_nsec = ns % 1000000000; 106 | ts.tv_sec += ns / 1000000000; 107 | ts.tv_sec += ms / 1000; 108 | 109 | if (sem_timedwait(&(semaphoreHandle->pSemaphore), &ts) != 0) 110 | #endif 111 | { 112 | return true; 113 | } 114 | else 115 | { 116 | return false; 117 | } 118 | } 119 | 120 | void Semaphore::release() 121 | { 122 | if (NULL == semaphoreHandle) 123 | { 124 | return; 125 | } 126 | 127 | #ifdef _WIN32 128 | // windows 129 | ReleaseSemaphore(semaphoreHandle->pSemaphore, 1, NULL); 130 | #else 131 | // linux 132 | sem_post(&(semaphoreHandle->pSemaphore)); 133 | #endif 134 | } 135 | 136 | } // namespace Wz -------------------------------------------------------------------------------- /Semaphore.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _SEMAPHORE_H_ 3 | #define _SEMAPHORE_H_ 4 | 5 | #include 6 | 7 | namespace Wz 8 | { 9 | 10 | struct SemaphoreHandle; 11 | 12 | class Semaphore 13 | { 14 | public: 15 | Semaphore(const int &value = 0); 16 | ~Semaphore(); 17 | 18 | void wait(); // semaphore - 1 19 | bool wait(const unsigned int &ms); // semaphore - 1 , timeout ms 20 | void release(); // semaphore + 1 21 | 22 | private: 23 | SemaphoreHandle *semaphoreHandle; 24 | }; 25 | 26 | } // namespace Wz 27 | 28 | #endif -------------------------------------------------------------------------------- /Thread.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "Thread.h" 3 | 4 | #ifdef _WIN32 5 | // windows 6 | #include 7 | #include 8 | #else 9 | // linux 10 | #include 11 | #include 12 | #include 13 | #endif 14 | 15 | namespace Wz 16 | { 17 | 18 | #ifdef _WIN32 19 | // windows 20 | struct ThreadHandle 21 | { 22 | HANDLE pThread; 23 | }; 24 | 25 | unsigned int static __stdcall threadCallBack(void *p) 26 | { 27 | Thread *t = (Thread *)p; 28 | t->run(); 29 | return 0; 30 | } 31 | #else 32 | // linux 33 | struct ThreadHandle 34 | { 35 | pthread_t pThread; 36 | }; 37 | 38 | static void *threadCallBack(void *p) 39 | { 40 | Thread *t = (Thread *)p; 41 | t->run(); 42 | return NULL; 43 | } 44 | #endif 45 | 46 | Thread::Thread() 47 | : runnable(NULL), threadHandle(NULL) 48 | { 49 | } 50 | 51 | Thread::Thread(Runnable runnable) 52 | : runnable(runnable), threadHandle(NULL) 53 | { 54 | } 55 | 56 | Thread::~Thread() 57 | { 58 | if (threadHandle) 59 | { 60 | delete threadHandle; 61 | threadHandle = NULL; 62 | } 63 | } 64 | 65 | void Thread::setRunnable(Runnable runnable) 66 | { 67 | this->runnable = runnable; 68 | } 69 | 70 | void Thread::run() 71 | { 72 | if (NULL != runnable) 73 | { 74 | runnable(); 75 | } 76 | } 77 | 78 | void Thread::start() 79 | { 80 | threadHandle = new ThreadHandle; 81 | #ifdef _WIN32 82 | // windows 83 | unsigned int threadId; 84 | threadHandle->pThread = (HANDLE)_beginthreadex(NULL, 85 | 0, 86 | threadCallBack, 87 | this, 88 | 0, 89 | &threadId); 90 | if (0 == threadHandle->pThread) 91 | #else 92 | // linux 93 | if (0 != pthread_create(&(threadHandle->pThread), 94 | NULL, 95 | threadCallBack, 96 | this)) 97 | #endif 98 | { 99 | delete threadHandle; 100 | threadHandle = NULL; 101 | 102 | printf("Thread: thread create failed."); 103 | return; 104 | } 105 | } 106 | 107 | void Thread::join() 108 | { 109 | if (threadHandle) 110 | { 111 | #ifdef _WIN32 112 | // windows 113 | WaitForSingleObject(threadHandle->pThread, INFINITE); 114 | CloseHandle(threadHandle->pThread); 115 | #else 116 | // linux 117 | pthread_join(threadHandle->pThread, NULL); 118 | #endif 119 | delete threadHandle; 120 | threadHandle = NULL; 121 | } 122 | } 123 | 124 | void Thread::sleepS(const unsigned int &s) 125 | { 126 | #ifdef _WIN32 127 | // windows 128 | Sleep(s * 1000); 129 | #else 130 | // linux 131 | sleep(s); 132 | #endif 133 | } 134 | 135 | void Thread::sleepMs(const unsigned int &ms) 136 | { 137 | #ifdef _WIN32 138 | // windows 139 | Sleep(ms); 140 | #else 141 | // linux 142 | usleep(ms * 1000); 143 | #endif 144 | } 145 | 146 | } // namespace Wz -------------------------------------------------------------------------------- /Thread.h: -------------------------------------------------------------------------------- 1 | 2 | #ifndef _THREAD_H_ 3 | #define _THREAD_H_ 4 | 5 | #include 6 | 7 | namespace Wz 8 | { 9 | 10 | typedef void (*Runnable)(); 11 | 12 | struct ThreadHandle; 13 | 14 | class Thread 15 | { 16 | public: 17 | Thread(); 18 | Thread(Runnable runnable); 19 | virtual ~Thread(); 20 | 21 | void setRunnable(Runnable runnable); 22 | 23 | virtual void run(); 24 | 25 | void start(); 26 | void join(); 27 | 28 | static void sleepS(const unsigned int &s); 29 | static void sleepMs(const unsigned int &ms); 30 | 31 | private: 32 | Runnable runnable; 33 | ThreadHandle *threadHandle; 34 | }; 35 | 36 | } // namespace Wz 37 | 38 | #endif -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include "Thread.h" 4 | #include "Mutex.h" 5 | #include "Semaphore.h" 6 | 7 | using namespace std; 8 | 9 | Wz::Mutex mutex; 10 | Wz::Semaphore semaphore(1); 11 | 12 | unsigned int tmp = 0; 13 | 14 | void thread1() 15 | { 16 | // mutex.lock(); 17 | 18 | for (int i = 0; i < 100; i++) 19 | { 20 | if (0 == i % 10) 21 | { 22 | semaphore.release(); 23 | } 24 | 25 | tmp += i; 26 | printf("threa1: %d\n", tmp); 27 | Wz::Thread::sleepMs(200); 28 | } 29 | 30 | // mutex.unlock(); 31 | } 32 | 33 | class Thread2 : public Wz::Thread 34 | { 35 | public: 36 | void run() 37 | { 38 | // mutex.lock(); 39 | 40 | for (int i = 0; i < 100; i++) 41 | { 42 | semaphore.wait(); 43 | 44 | tmp -= i; 45 | printf("threa2: %d\n", tmp); 46 | Wz::Thread::sleepMs(300); 47 | } 48 | 49 | // mutex.unlock(); 50 | } 51 | }; 52 | 53 | int main(int argc, char **argv) 54 | { 55 | printf("------Thread------\n"); 56 | 57 | Wz::Thread t1(&thread1); 58 | t1.start(); 59 | 60 | Thread2 t2; 61 | t2.start(); 62 | 63 | getchar(); 64 | 65 | return 0; 66 | } --------------------------------------------------------------------------------