diff --git a/job/semaphore.hpp b/job/semaphore.hpp index df468351..19be001b 100644 --- a/job/semaphore.hpp +++ b/job/semaphore.hpp @@ -32,6 +32,7 @@ namespace util::job { semaphore& operator= (semaphore&&) = delete; int acquire (void); + int acquire (int count); int release (void); auto lock (void) { return acquire (); } diff --git a/job/semaphore_linux.cpp b/job/semaphore_linux.cpp index 6e2c3147..be127e21 100644 --- a/job/semaphore_linux.cpp +++ b/job/semaphore_linux.cpp @@ -50,16 +50,18 @@ semaphore::semaphore (int initial): /////////////////////////////////////////////////////////////////////////////// int -semaphore::acquire (void) +semaphore::acquire (int count) { + CHECK_GE (count, 0); + do { int now = m_value; // if our value is positive then attempt to decrement it and return, // else retry because someone interfered with us. - if (now > 0) { - if (m_value.compare_exchange_weak (now, now - 1)) - return now - 1; + if (now - count >= 0) { + if (m_value.compare_exchange_weak (now, now - count)) + return now - count; continue; } @@ -67,16 +69,24 @@ semaphore::acquire (void) // there's been a modification and retry. if (-1 == sys_futex (&m_value, FUTEX_WAIT, now, nullptr, nullptr, 0)) { switch (errno) { - case EAGAIN: break; - case EINTR: break; - default: - posix::error::throw_code (); + case EAGAIN: break; + case EINTR: break; + default: + posix::error::throw_code (); } } } while (1); } +//----------------------------------------------------------------------------- +int +semaphore::acquire (void) +{ + return acquire (1); +} + + //----------------------------------------------------------------------------- int semaphore::release (void)