You actually only need a cas and a condition variable (technically the 
condition in Go requires a backing lock, but if you have wait/notify it isn’t 
needed).

You can read this 
https://code.woboq.org/userspace/glibc/nptl/pthread_rwlock_common.c.html 
<https://code.woboq.org/userspace/glibc/nptl/pthread_rwlock_common.c.html> 
and/or https://6826.csail.mit.edu/2019/papers/HO17.pdf 
<https://6826.csail.mit.edu/2019/papers/HO17.pdf> for the general idea.

Essentially, you use some bits of the ‘atomic value’ to encode phases (waiting 
for write lock, holding write lock, reader bits) - and use the cond variable to 
block the writers (or readers for that matter) and loop and retry the cas.

The following is simplified since it isn’t “fair”, but you can add another bit 
for “writer waiting” to accomplish this. Also, the ‘condition’ must be a ‘flag’ 
so that a signal() with no waiters is satisfied by the next wait()

bits 0 - 30 number of readers
bits 31 writer has lock

WRITER = 1<<31
read() is the atomic read of v

pseudo code

try_lock() {
  for {
          v = read()
          if v has writer {
              return WOULD_BLOCK
          }
          if(cas(v,v + 1 reader)) {
              return OK
          } else {
             // loop and try again
         }
  }
}

runlock() {
   for{
      v = read()
      if(cas(v,v -1 reader)) {
         cond.signal() // can be optimized to not always do this, i.e. only 
when readers is 0
         return
      } else {
         // loop and try again
      }
  }
}

wlock() {
   for {
      v = read()
      if v !=0 { 
         cond.wait()
     }
     else {
        if(cas(v,WRITER)) {  // we are the writer
            return
        } else {
            // loop and try again
        }
    }
}

wunlock() {
    set(v,0);
    cond.signal() // for other waiting writers
}

Obviously if you need readers to block on writers (i.e. rlock() ) it is 
slightly more work, but you get the idea.


> On Dec 3, 2019, at 7:54 PM, Liam <networkimp...@gmail.com> wrote:
> 
> Busy means would-block, yes.
> 
> Burak thanks, but that doesn't work for read-lock.
> 
> On Tuesday, December 3, 2019 at 5:39:48 PM UTC-8, Robert Engels wrote:
> It depends then, because technically the Go RW lock queues readers behind a 
> waiting writer so “busy” is somewhat undefined. If “busy” means “would block” 
> you can still do it - I’ll post the code tonight. 
> 
> > On Dec 3, 2019, at 6:49 PM, Robert Engels <ren...@ix.netcom.com <>> wrote: 
> > 
> > I would use an atomic and a lock instead of two locks. 
> > 
> >>> On Dec 3, 2019, at 6:35 PM, burak serdar <bse...@computer.org <>> wrote: 
> >>> 
> >>> On Tue, Dec 3, 2019 at 5:21 PM Liam Breck <networ...@gmail.com <>> 
> >>> wrote: 
> >>> 
> >>> I have a problem that is trivially solved via 
> >>> 
> >>> door sync.RWMutex 
> >>> 
> >>> func Reader() T { 
> >>>  if !door.TryRLock() { // missing in stdlib :-( 
> >>>     return busy 
> >>>  } 
> >>>  defer door.RUnlock() 
> >>>  ... 
> >>> } 
> >>> 
> >>> func Writer() { 
> >>>  door.Lock() 
> >>>  defer door.Unlock() 
> >>>  ... 
> >>> } 
> >>> 
> >>> How does one achieve this in Go? 
> >> 
> >> Two locks and a bool? 
> >> 
> >> var door=sync.Mutex{} 
> >> var x=sync.Mutex{} 
> >> var b bool 
> >> 
> >> func trylock() bool { 
> >> x.Lock() 
> >> if b { 
> >> x.Unlock() 
> >> return false 
> >> } 
> >> b=true 
> >> door.Lock() 
> >> x.Unlock() 
> >> return true 
> >> } 
> >> 
> >> unlock: 
> >> 
> >> x.Lock() 
> >> b=false 
> >> door.Unlock() 
> >> x.Unlock() 
> >> 
> >> 
> >> 
> >> 
> >>> 
> >>> -- 
> >>> You received this message because you are subscribed to the Google Groups 
> >>> "golang-nuts" group. 
> >>> To unsubscribe from this group and stop receiving emails from it, send an 
> >>> email to golan...@googlegroups.com <>. 
> >>> To view this discussion on the web visit 
> >>> https://groups.google.com/d/msgid/golang-nuts/CAKvHMgTO%3DxfFQ_u7aO9UE-1vHHEKmdhr47sro2mnp6DkEb6mPA%40mail.gmail.com
> >>>  
> >>> <https://groups.google.com/d/msgid/golang-nuts/CAKvHMgTO%3DxfFQ_u7aO9UE-1vHHEKmdhr47sro2mnp6DkEb6mPA%40mail.gmail.com>.
> >>>  
> >> 
> >> -- 
> >> You received this message because you are subscribed to the Google Groups 
> >> "golang-nuts" group. 
> >> To unsubscribe from this group and stop receiving emails from it, send an 
> >> email to golan...@googlegroups.com <>. 
> >> To view this discussion on the web visit 
> >> https://groups.google.com/d/msgid/golang-nuts/CAMV2RqrDeBNhkeswg%2BhdCf1kSzMEJduota%3D6UrNq4z2PQRtzEQ%40mail.gmail.com
> >>  
> >> <https://groups.google.com/d/msgid/golang-nuts/CAMV2RqrDeBNhkeswg%2BhdCf1kSzMEJduota%3D6UrNq4z2PQRtzEQ%40mail.gmail.com>.
> >>  
> 
> 
> -- 
> You received this message because you are subscribed to the Google Groups 
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an 
> email to golang-nuts+unsubscr...@googlegroups.com 
> <mailto:golang-nuts+unsubscr...@googlegroups.com>.
> To view this discussion on the web visit 
> https://groups.google.com/d/msgid/golang-nuts/022a5bb5-be27-4721-afe4-7e08f4531a3d%40googlegroups.com
>  
> <https://groups.google.com/d/msgid/golang-nuts/022a5bb5-be27-4721-afe4-7e08f4531a3d%40googlegroups.com?utm_medium=email&utm_source=footer>.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/golang-nuts/87A9A2B9-B777-47AA-9AF9-A5A27EB705F4%40ix.netcom.com.

Reply via email to