|
Boost : |
From: Alexander Terekhov (terekhov_at_[hidden])
Date: 2003-10-18 13:39:44
Rene Rivera wrote:
[...]
> Your code is basically identical to that provided by
> boost::detail::lightweight_mutex. See boost/detail/lightweight_mutex*.hpp
<Forward Inline>
To: pthreads-win32_at_[hidden]
Subject: mutexes: "food for thought"
G'Day,
here's "ala futex based" mutex stuff using XCHG.
No need for CAS. I hope that it will work just fine.
Can you see any harmful race condition(s) here?
TIA.
#define SWAP_BASED_MUTEX_FOR_WINDOWS_INITIALIZER { 0, 0 }
struct swap_based_mutex_for_windows {
atomic<int> m_lock_status; // -1: free, 0: locked, 1 lock-contention
atomic<auto_reset_event *> m_retry_event; // DCSI'd
void DCSI(); // double-checked serialized initialization
void slow_lock();
bool slow_trylock();
bool slow_timedlock(absolute_timeout const & timeout);
void release_one_waiter_if_any();
void lock() {
if (m_lock_status.swap(0, msync::acq) >= 0) slow_lock();
}
bool trylock() {
return (m_lock_status.swap(0, msync::acq) < 0) ? true : slow_trylock();
}
bool timedlock(absolute_timeout const & timeout) {
return (m_lock_status.swap(0, msync::acq) < 0) ? true : slow_timedlock(timeout);
}
void unlock() {
if (m_lock_status.swap(-1, msync::rel) > 0) release_one_waiter_if_any();
}
};
void swap_based_mutex_for_windows::slow_lock() {
DCSI();
while (m_lock_status.swap(1, msync::acq) >= 0)
m_retry_event.load(msync::none)->wait();
}
bool swap_based_mutex_for_windows::slow_trylock() {
DCSI();
return m_lock_status.swap(1, msync::acq) < 0;
}
bool swap_based_mutex_for_windows::slow_timedlock(absolute_timeout const & timeout) {
DCSI();
while (m_lock_status.swap(1, msync::acq) >= 0)
if (!m_retry_event.load(msync::none)->timedwait(timeout)) return false;
return true;
}
void swap_based_mutex_for_windows::release_one_waiter_if_any() {
m_retry_event.load(msync::none)->set();
}
void swap_based_mutex_for_windows::DCSI() {
if (!m_retry_event.load(msync::none)) {
named_windows_mutex_trick guard(this);
if (!m_retry_event.load(msync::none)) {
m_retry_event.store(new auto_reset_event(), msync::rel);
m_lock_status.store(-1, msync::rel);
}
}
}
regards,
alexander.
P.S. I've never run it. Just a sketch.
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk