Timed wait operation for semaphore
This commit is contained in:
parent
da8e88f9f3
commit
520ae553f0
2 changed files with 61 additions and 2 deletions
|
|
@ -8,6 +8,7 @@
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <cerrno>
|
#include <cerrno>
|
||||||
|
#include <ctime>
|
||||||
|
|
||||||
RTSemaphore::RTSemaphore(unsigned value)
|
RTSemaphore::RTSemaphore(unsigned value)
|
||||||
{
|
{
|
||||||
|
|
@ -57,6 +58,15 @@ bool RTSemaphore::try_wait()
|
||||||
return b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RTSemaphore::timed_wait(uint32_t milliseconds)
|
||||||
|
{
|
||||||
|
std::error_code ec;
|
||||||
|
bool b = timed_wait(milliseconds, ec);
|
||||||
|
if (ec)
|
||||||
|
throw std::system_error(ec);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(__APPLE__)
|
#if defined(__APPLE__)
|
||||||
void RTSemaphore::init(std::error_code& ec, unsigned value)
|
void RTSemaphore::init(std::error_code& ec, unsigned value)
|
||||||
{
|
{
|
||||||
|
|
@ -100,10 +110,17 @@ void RTSemaphore::wait(std::error_code& ec) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RTSemaphore::try_wait(std::error_code& ec) noexcept
|
bool RTSemaphore::try_wait(std::error_code& ec) noexcept
|
||||||
|
{
|
||||||
|
return timed_wait(0, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RTSemaphore::timed_wait(uint32_t milliseconds, std::error_code& ec) noexcept
|
||||||
{
|
{
|
||||||
ec.clear();
|
ec.clear();
|
||||||
do {
|
do {
|
||||||
const mach_timespec_t timeout = { 0, 0 };
|
mach_timespec_t timeout;
|
||||||
|
timeout.tv_sec = milliseconds / 1000;
|
||||||
|
timeout.tv_nsec = (milliseconds % 1000) * (1000L * 1000L);
|
||||||
kern_return_t ret = semaphore_timedwait(sem_, timeout);
|
kern_return_t ret = semaphore_timedwait(sem_, timeout);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case KERN_SUCCESS:
|
case KERN_SUCCESS:
|
||||||
|
|
@ -178,9 +195,14 @@ void RTSemaphore::wait(std::error_code& ec) noexcept
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RTSemaphore::try_wait(std::error_code& ec) noexcept
|
bool RTSemaphore::try_wait(std::error_code& ec) noexcept
|
||||||
|
{
|
||||||
|
return timed_wait(0, ec);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RTSemaphore::timed_wait(uint32_t milliseconds, std::error_code& ec) noexcept
|
||||||
{
|
{
|
||||||
ec.clear();
|
ec.clear();
|
||||||
DWORD ret = WaitForSingleObject(sem_, 0);
|
DWORD ret = WaitForSingleObject(sem_, milliseconds);
|
||||||
switch (ret) {
|
switch (ret) {
|
||||||
case WAIT_OBJECT_0:
|
case WAIT_OBJECT_0:
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -251,4 +273,38 @@ bool RTSemaphore::try_wait(std::error_code& ec) noexcept
|
||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool absolute_timeout(uint32_t milliseconds, timespec &abs, std::error_code& ec)
|
||||||
|
{
|
||||||
|
timespec now;
|
||||||
|
if (clock_gettime(CLOCK_REALTIME, &now) != 0) {
|
||||||
|
ec = std::error_code(errno, std::generic_category());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
abs.tv_sec = now.tv_sec + milliseconds / 1000;
|
||||||
|
abs.tv_nsec = now.tv_nsec + (milliseconds % 1000) * (1000L * 1000L);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool RTSemaphore::timed_wait(uint32_t milliseconds, std::error_code& ec) noexcept
|
||||||
|
{
|
||||||
|
ec.clear();
|
||||||
|
timespec abs;
|
||||||
|
if (!absolute_timeout(milliseconds, abs, ec))
|
||||||
|
return false;
|
||||||
|
do {
|
||||||
|
if (sem_timedwait(&sem_, &abs) == 0)
|
||||||
|
return true;
|
||||||
|
int e = errno;
|
||||||
|
switch (e) {
|
||||||
|
case EINTR:
|
||||||
|
break;
|
||||||
|
case ETIMEDOUT:
|
||||||
|
return false;
|
||||||
|
default:
|
||||||
|
ec = std::error_code(e, std::generic_category());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} while (1);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@
|
||||||
#else
|
#else
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
#endif
|
#endif
|
||||||
|
#include <cstdint>
|
||||||
#include <system_error>
|
#include <system_error>
|
||||||
|
|
||||||
class RTSemaphore {
|
class RTSemaphore {
|
||||||
|
|
@ -28,10 +29,12 @@ public:
|
||||||
void post();
|
void post();
|
||||||
void wait();
|
void wait();
|
||||||
bool try_wait();
|
bool try_wait();
|
||||||
|
bool timed_wait(uint32_t milliseconds);
|
||||||
|
|
||||||
void post(std::error_code& ec) noexcept;
|
void post(std::error_code& ec) noexcept;
|
||||||
void wait(std::error_code& ec) noexcept;
|
void wait(std::error_code& ec) noexcept;
|
||||||
bool try_wait(std::error_code& ec) noexcept;
|
bool try_wait(std::error_code& ec) noexcept;
|
||||||
|
bool timed_wait(uint32_t milliseconds, std::error_code& ec) noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void init(std::error_code& ec, unsigned value);
|
void init(std::error_code& ec, unsigned value);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue