Google Groups Home
Help | Sign in
fast-pathed rw-mutex with single eventcount for the slow-path...
There are currently too many topics in this group that display first. To make this topic appear first, remove this option from another topic.
There was an error processing your request. Please try again.
flag
  4 messages - Collapse all
The group you are posting to is a Usenet group. Messages posted to this group will make your email address visible to anyone on the Internet.
Your reply message has not been sent.
Your post was successful
Chris Thomasson  
View profile
 More options Oct 31 2006, 3:16 am
Newsgroups: comp.programming.threads
From: "Chris Thomasson" <cris...@comcast.net>
Date: Tue, 31 Oct 2006 00:16:32 -0800
Local: Tues, Oct 31 2006 3:16 am
Subject: fast-pathed rw-mutex with single eventcount for the slow-path...
Here is an example of how you can use an eventcount to help implement a
speedy fast-pathed rw-mutex...

class rwmutex {
  typedef unsigned int state_t;

  enum flags_e {
    WRITER_FLAG = 0x80000000,
    READER_MASK = 0x7FFFFFFF
  };

private:
  mutable state_t volatile m_state;
  eventcount m_waiters;

public:
  rwmutex() : m_state(0) {}

public:
  void rdlock() const {
    state_t local = ATOMIC_INC(&m_state);
    while (local & WRITER_FLAG) {
      eventcount::count_t waits = m_waiters.get();
      local = ATOMIC_LOAD(&m_state);
      if (! (local & WRITER_FLAG)) { return; }
      m_waiters.wait(waits);
      local = ATOMIC_LOAD(&m_state);
    }
  }

  void wrlock() {
    do {
      state_t local = ATOMIC_LOAD(&m_state);
      while (local) {
        eventcount::count_t waits = m_waiters.get();
        local = ATOMIC_LOAD(&m_state);
        if (! local) { break; }
        m_waiters.wait(waits);
        local = ATOMIC_LOAD(&m_state);
      }
    } while(! ATOMIC_CAS(&m_state, local, local | WRITER_FLAG));
  }

public:
  void unlock() const {
    local = m_state;
    if(local & READER_MASK) {
      if (! ATOMIC_DEC(&m_state)) {
        // atomic-op free fast-path...
        m_waiters.signal();
      }
    } else {
      // m_state &= ~WRITER_FLAG
      ATOMIC_AND_NOT(&m_state, WRITER_FLAG);

      // atomic-op free fast-path...
      m_waiters.broadcast();
    }
  }

};

What do you think here? Look okay to you Joe?

:^)


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Joe Seigh  
View profile
 More options Oct 31 2006, 9:05 am
Newsgroups: comp.programming.threads
From: Joe Seigh <jseigh...@xemaps.com>
Date: Tue, 31 Oct 2006 09:05:02 -0500
Local: Tues, Oct 31 2006 9:05 am
Subject: Re: fast-pathed rw-mutex with single eventcount for the slow-path...

Chris Thomasson wrote:
> Here is an example of how you can use an eventcount to help implement a
> speedy fast-pathed rw-mutex...

[...]

> What do you think here? Look okay to you Joe?

> :^)

I'm going to wait for you to do your 3 or 4 corrections
first. :)

One thing you have to be careful with is the memory barrier
interaction between the eventcount and the lock-free
data structures.  If the latter doesn't provide them then
eventcount has to.  In some respects condvar is easier to
implement since the mutex provides memory synchronization
independent of the data structure implementation.

--
Joe Seigh

When you get lemons, you make lemonade.
When you get hardware, you make software.


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Peter Dimov  
View profile
 More options Oct 31 2006, 6:05 pm
Newsgroups: comp.programming.threads
From: "Peter Dimov" <pdi...@gmail.com>
Date: 31 Oct 2006 15:05:48 -0800
Local: Tues, Oct 31 2006 6:05 pm
Subject: Re: fast-pathed rw-mutex with single eventcount for the slow-path...

Chris Thomasson wrote:
> Here is an example of how you can use an eventcount to help implement a
> speedy fast-pathed rw-mutex...

[...]

> public:
>   void rdlock() const {
>     state_t local = ATOMIC_INC(&m_state);

[...]

>   void wrlock() {
>     do {
>       state_t local = ATOMIC_LOAD(&m_state);
>       while (local) {

Starving writers? :-)

    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
Chris Thomasson  
View profile
 More options Nov 4 2006, 7:20 am
Newsgroups: comp.programming.threads
From: "Chris Thomasson" <cris...@comcast.net>
Date: Sat, 4 Nov 2006 04:20:24 -0800
Local: Sat, Nov 4 2006 7:20 am
Subject: Re: fast-pathed rw-mutex with single eventcount for the slow-path...
"Peter Dimov" <pdi...@gmail.com> wrote in message

news:1162335948.140616.223940@e64g2000cwd.googlegroups.com...

> Chris Thomasson wrote:
>> Here is an example of how you can use an eventcount to help implement a
>> speedy fast-pathed rw-mutex...

[...]

> Starving writers? :-)

This one happens to... However, it's fairly trivial to change this behavior
in my algorithm...

Tell me, what do you think of the following approach:

class rwmutex {
  typedef unsigned int state_t;

  enum flags_e {
    WRITER_FLAG = 0x80000000,
    READER_MASK = 0x0FFFFFFF
  };

private:
  mutable state_t volatile m_state;
  eventcount m_waiters;

public:
  rwmutex() : m_state(0) {}

public:
  void rdlock() const {
    state_t local = ATOMIC_INC(&m_state);
    while(local & WRITER_FLAG) {
      if (ATOMIC_CAS(&m_state, local, local - 1)) {
        eventcount::count_t waits = m_waiters.get();
        local = ATOMIC_LOAD(&m_state);
        if (local & WRITER_FLAG) {
          m_waiters.wait(waits);
        }
        local = ATOMIC_INC(&m_state);
      } else {
        local = ATOMIC_LOAD(&m_state);
      }
    }
  }

  void wrlock() {
    while(! ATOMIC_BTS(&m_state, WRITER_FLAG)) {
      eventcount::count_t waits = m_waiters.get();
      if (! ATOMIC_BTS(&m_state, WRITER_FLAG)) {
        m_waiters.wait(waits);
      }
    }

    state_t local = ATOMIC_LOAD(&m_state);
    while (local & READER_MASK) {
      eventcount::count_t waits = m_waiters.get();
      local = ATOMIC_LOAD(&m_state);
      if (! (local & READER_MASK)) { return; }
      m_waiters.wait(waits);
      local = ATOMIC_LOAD(&m_state);
    }
  }

public:
  void unlock() const {
    state_t local = m_state;
    if (local & READER_MASK) {
      local = ATOMIC_DEC(&m_state);
      if (! local || local & WRITER_FLAG) {
        // atomic-op free fast-path...
        m_waiters.signal();
      }
    } else {
      // m_state &= ~WRITER_FLAG
      ATOMIC_AND_NOT(&m_state, WRITER_FLAG);

      // atomic-op free fast-path...
      m_waiters.broadcast();
    }
  }

};

This version will not starve any writers...

;^)


    Reply to author    Forward  
You must Sign in before you can post messages.
To post a message you must first join this group.
Please update your nickname on the subscription settings page before posting.
You do not have the permission required to post.
End of messages
« Back to Discussions « Newer topic     Older topic »

Create a group - Google Groups - Google Home - Terms of Service - Privacy Policy
©2008 Google