#include "src/base/platform/semaphore.h"
#if V8_OS_DARWIN
#include <dispatch/dispatch.h>
#elif V8_OS_WIN
#include <windows.h>
#endif
#include <errno.h>
#include "src/base/logging.h"
#include "src/base/platform/elapsed-timer.h"
#include "src/base/platform/time.h"
namespace v8 {
namespace base {
#if V8_OS_DARWIN
Semaphore::Semaphore(int count) {
native_handle_ = dispatch_semaphore_create(count);
DCHECK(native_handle_);
}
Semaphore::~Semaphore() { dispatch_release(native_handle_); }
void Semaphore::Signal() { dispatch_semaphore_signal(native_handle_); }
void Semaphore::Wait() {
dispatch_semaphore_wait(native_handle_, DISPATCH_TIME_FOREVER);
}
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
dispatch_time_t timeout =
dispatch_time(DISPATCH_TIME_NOW, rel_time.InNanoseconds());
return dispatch_semaphore_wait(native_handle_, timeout) == 0;
}
#elif V8_OS_POSIX
Semaphore::Semaphore(int count) { … }
Semaphore::~Semaphore() { … }
void Semaphore::Signal() { … }
void Semaphore::Wait() { … }
bool Semaphore::WaitFor(const TimeDelta& rel_time) { … }
#elif V8_OS_WIN
Semaphore::Semaphore(int count) {
DCHECK_GE(count, 0);
native_handle_ = ::CreateSemaphoreA(nullptr, count, 0x7FFFFFFF, nullptr);
DCHECK_NOT_NULL(native_handle_);
}
Semaphore::~Semaphore() {
BOOL result = CloseHandle(native_handle_);
DCHECK(result);
USE(result);
}
void Semaphore::Signal() {
LONG dummy;
BOOL result = ReleaseSemaphore(native_handle_, 1, &dummy);
DCHECK(result);
USE(result);
}
void Semaphore::Wait() {
DWORD result = WaitForSingleObject(native_handle_, INFINITE);
DCHECK(result == WAIT_OBJECT_0);
USE(result);
}
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
TimeTicks now = TimeTicks::Now();
TimeTicks end = now + rel_time;
while (true) {
int64_t msec = (end - now).InMilliseconds();
if (msec >= static_cast<int64_t>(INFINITE)) {
DWORD result = WaitForSingleObject(native_handle_, INFINITE - 1);
if (result == WAIT_OBJECT_0) {
return true;
}
DCHECK(result == WAIT_TIMEOUT);
now = TimeTicks::Now();
} else {
DWORD result = WaitForSingleObject(
native_handle_, (msec < 0) ? 0 : static_cast<DWORD>(msec));
if (result == WAIT_TIMEOUT) {
return false;
}
DCHECK(result == WAIT_OBJECT_0);
return true;
}
}
}
#elif V8_OS_STARBOARD
Semaphore::Semaphore(int count) : native_handle_(count) { DCHECK_GE(count, 0); }
Semaphore::~Semaphore() {}
void Semaphore::Signal() { native_handle_.Put(); }
void Semaphore::Wait() { native_handle_.Take(); }
bool Semaphore::WaitFor(const TimeDelta& rel_time) {
int64_t microseconds = rel_time.InMicroseconds();
return native_handle_.TakeWait(microseconds);
}
#endif
}
}