#define UNEXPECTED_ERROR_WIN() \
UNEXPECTED_ERROR(GetLastError() == ERROR_SUCCESS)
class semaphore {
LONG m_count;
HANDLE m_waitset;
public:
semaphore(LONG count = 0)
: m_count(count),
m_waitset(CreateSemaphore(NULL, 0, LONG_MAX, NULL)) {
if (m_count < 0 || ! m_waitset) {
if (m_waitset) CloseHandle(m_waitset);
assert(m_count > -1 && m_waitset);
throw std::exception();
}
}
~semaphore() throw() {
if (m_count < 0) {
UNEXPECTED_ERROR(m_count > -1);
} else if (! CloseHandle(m_waitset)) {
UNEXPECTED_ERROR_WIN();
}
}
public:
void post(LONG count = 1) throw() {
if (count < 1) {
UNEXPECTED_ERROR(count > 0);
}
LONG old_count = InterlockedExchangeAdd(&m_count, count);
if (old_count < 0) {
if (! ReleaseSemaphore(m_waitset,
(-old_count) > count ? count : -old_count, NULL)) {
UNEXPECTED_ERROR_WIN();
}
}
}
void wait() throw() {
if (InterlockedDecrement(&m_count) < 0) {
if (WaitForSingleObject(m_waitset, INFINITE) !=
WAIT_OBJECT_0) {
UNEXPECTED_ERROR_WIN();
}
}
}
};
___________________________________________________________________
I kept the timeout logic out for brevity. That part has not changed any, it
can be kept the same. Enjoy!
;^D
> I kept the timeout logic out for brevity. That part has not changed any,
> it can be kept the same. Enjoy!
Joes semaphore hands off ownership on contention.
Here is one that does not:
____________________________________________________________
class semaphore {
LONG volatile m_state;
eventcount m_ecount;
public:
void post(LONG count = 1) {
InterlockedExchangeAdd(&m_state, count);
if (count == 1) {
m_ecount.signal_relaxed();
} else {
m_ecount.broadcast_relaxed();
}
}
void wait() {
LONG cmp;
while (! (cmp = m_state) ||
InterlockedCompareExchange(
&m_state, cmp, cmp - 1) != cmp) {
eventcount::key_type key = m_ecount.get();
if ((cmp = m_state) &&
InterlockedCompareExchange(
&m_state, cmp, cmp - 1) == cmp) {
break;
}
m_ecount.wait(key);
}
}
};
____________________________________________________________
I think that is broken. This might fix it:
____________________________________________________________
class semaphore {
LONG volatile m_state;
eventcount m_ecount;
bool prv_wait_cas() {
LONG cmptmp, cmp = m_state;
do {
cmptmp = cmp;
cmp = InterlockedCompareExchange(&m_state,
(cmp) ? cmp - 1 : 0, cmp);
} while (cmp != cmptmp);
return (cmp);
}
public:
void post(LONG count = 1) {
InterlockedExchangeAdd(&m_state, count);
if (count == 1) {
m_ecount.signal_relaxed();
} else {
m_ecount.broadcast_relaxed();
}
}
void wait() {
while (! prv_wait_cas()) {
eventcount::key_type key = m_ecount.get();
if (prv_wait_cas()) break;
m_ecount.wait(key);
}
}
};
____________________________________________________________