ref: a68e92f1e80f262e04d6e6c1d27af80199afbdc0
dir: /lib/thread/rwlock.myr/
use "mutex"
pkg thread =
/*
`_lock` grants exclusive access to either n readers or one writer.
`_rlock` protects `_rcount` and allows the first reader to attempt to
lock `_lockk` without letting other readers in.
*/
type rwlock = struct
_lock : mutex
_rlock : mutex
_rcount : uint32
;;
const mkrwlock : (-> rwlock)
const rdlock : (rw : rwlock# -> void)
const wrlock : (rw : rwlock# -> void)
const tryrdlock : (rw : rwlock# -> bool)
const trywrlock : (rw : rwlock# -> bool)
const rdunlock : (rw : rwlock# -> void)
const wrunlock : (rw : rwlock# -> void)
;;
const mkrwlock = {
-> [._lock = mkmtx(), ._rlock = mkmtx()]
}
const rdlock = {rw
mtxlock(&rw._rlock)
/*
The first reader either successfully acquires `_lock`, locking out all
writers, or blocks while holding `_rlock`, locking out all other
readers until it is able to acquire `_lock`, meaning that a writer has
released it.
*/
if rw._rcount++ == 0
mtxlock(&rw._lock)
;;
mtxunlock(&rw._rlock)
}
const wrlock = {rw
mtxlock(&rw._lock)
}
const tryrdlock = {rw
var rc = true
mtxlock(&rw._rlock)
if rw._rcount++ == 0
if !mtxtrylock(&rw._lock)
rw._rcount--
rc = false
;;
;;
mtxunlock(&rw._rlock)
-> rc
}
const trywrlock = {rw
-> mtxtrylock(&rw._lock)
}
const rdunlock = {rw
mtxlock(&rw._rlock)
/* `_lock` is not released until the last reader releases the lock. */
if --rw._rcount == 0
mtxunlock(&rw._lock)
;;
mtxunlock(&rw._rlock)
}
const wrunlock = {rw
mtxunlock(&rw._lock)
}