Boost logo

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