You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
170 lines
3.2 KiB
170 lines
3.2 KiB
//////////////////////////////////////////////////////////////////// |
|
// Semaphore.h |
|
// |
|
// Copyright 2007 cDc@seacave |
|
// Distributed under the Boost Software License, Version 1.0 |
|
// (See http://www.boost.org/LICENSE_1_0.txt) |
|
|
|
#ifndef __SEACAVE_SEMAPHORE_H__ |
|
#define __SEACAVE_SEMAPHORE_H__ |
|
|
|
|
|
// I N C L U D E S ///////////////////////////////////////////////// |
|
|
|
#include "Thread.h" |
|
|
|
#ifndef _MSC_VER |
|
#ifdef _SUPPORT_CPP11 |
|
#include <mutex> |
|
#include <condition_variable> |
|
#else |
|
#include "CriticalSection.h" |
|
#include <sys/time.h> |
|
#endif |
|
#endif |
|
|
|
|
|
// D E F I N E S /////////////////////////////////////////////////// |
|
|
|
|
|
namespace SEACAVE { |
|
|
|
// S T R U C T S /////////////////////////////////////////////////// |
|
|
|
class Semaphore |
|
{ |
|
#ifdef _MSC_VER |
|
public: |
|
Semaphore(unsigned count=0) { |
|
h = CreateSemaphore(NULL, count, MAXLONG, NULL); |
|
}; |
|
~Semaphore() { |
|
CloseHandle(h); |
|
}; |
|
|
|
void Clear(unsigned count=0) { |
|
CloseHandle(h); |
|
h = CreateSemaphore(NULL, count, MAXLONG, NULL); |
|
} |
|
|
|
void Signal() { |
|
ReleaseSemaphore(h, 1, NULL); |
|
} |
|
void Signal(unsigned count) { |
|
ASSERT(count > 0); |
|
ReleaseSemaphore(h, count, NULL); |
|
} |
|
|
|
void Wait() { |
|
WaitForSingleObject(h, INFINITE); |
|
} |
|
bool Wait(uint32_t millis) { |
|
return WaitForSingleObject(h, millis) == WAIT_OBJECT_0; |
|
} |
|
|
|
protected: |
|
HANDLE h; |
|
|
|
#elif !defined(_SUPPORT_CPP11) |
|
// pthread implementation |
|
public: |
|
Semaphore(unsigned c=0) : count(c) { pthread_cond_init(&cond, NULL); } |
|
~Semaphore() { pthread_cond_destroy(&cond); } |
|
|
|
void Clear(unsigned c=0) { |
|
cs.Clear(); |
|
pthread_cond_destroy(&cond); |
|
pthread_cond_init(&cond, NULL); |
|
count = c; |
|
} |
|
|
|
void Signal() { |
|
Lock l(cs); |
|
++count; |
|
pthread_cond_signal(&cond); |
|
} |
|
void Signal(unsigned c) { |
|
ASSERT(c > 0); |
|
for (unsigned i=0; i<c; ++i) |
|
Signal(); |
|
} |
|
|
|
void Wait() { |
|
Lock l(cs); |
|
while (!count) |
|
pthread_cond_wait(&cond, &cs.getMutex()); |
|
--count; |
|
} |
|
bool Wait(uint32_t millis) { |
|
Lock l(cs); |
|
if (count == 0) { |
|
timeval timev; |
|
gettimeofday(&timev, NULL); |
|
millis += timev.tv_usec/1000; |
|
timespec t = { |
|
timev.tv_sec + (millis/1000), |
|
(millis%1000)*1000*1000 |
|
}; |
|
pthread_cond_timedwait(&cond, &cs.getMutex(), &t); |
|
if (count == 0) |
|
return false; |
|
} |
|
--count; |
|
return true; |
|
} |
|
|
|
protected: |
|
pthread_cond_t cond; |
|
CriticalSection cs; |
|
unsigned count; |
|
|
|
#else |
|
// C++11 implementation |
|
public: |
|
Semaphore(unsigned c=0) : count(c) {} |
|
~Semaphore() {} |
|
|
|
void Clear(unsigned c=0) { |
|
std::lock_guard<std::mutex> lock{mtx}; |
|
count = c; |
|
} |
|
|
|
void Signal() { |
|
std::lock_guard<std::mutex> lock{mtx}; |
|
++count; |
|
cv.notify_one(); |
|
} |
|
void Signal(unsigned c) { |
|
ASSERT(c > 0); |
|
for (unsigned i=0; i<c; ++i) |
|
Signal(); |
|
} |
|
|
|
void Wait() { |
|
std::unique_lock<std::mutex> lock{mtx}; |
|
cv.wait(lock, [&] { return count > 0; }); |
|
--count; |
|
} |
|
bool Wait(uint32_t millis) { |
|
std::unique_lock<std::mutex> lock{mtx}; |
|
if (!cv.wait_for(lock, std::chrono::milliseconds(millis), [&] { return count > 0; })) |
|
return false; |
|
--count; |
|
return true; |
|
} |
|
|
|
protected: |
|
std::condition_variable cv; |
|
std::mutex mtx; |
|
unsigned count; |
|
#endif |
|
|
|
private: |
|
Semaphore(const Semaphore&); |
|
Semaphore& operator=(const Semaphore&); |
|
}; |
|
/*----------------------------------------------------------------*/ |
|
|
|
} // namespace SEACAVE |
|
|
|
#endif // __SEACAVE_SEMAPHORE_H__
|
|
|