diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /libgo/go/sync/rwmutex.go | |
download | cbb-gcc-4.6.4-upstream.tar.bz2 cbb-gcc-4.6.4-upstream.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'libgo/go/sync/rwmutex.go')
-rw-r--r-- | libgo/go/sync/rwmutex.go | 75 |
1 files changed, 75 insertions, 0 deletions
diff --git a/libgo/go/sync/rwmutex.go b/libgo/go/sync/rwmutex.go new file mode 100644 index 000000000..06fd0b0ff --- /dev/null +++ b/libgo/go/sync/rwmutex.go @@ -0,0 +1,75 @@ +// Copyright 2009 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package sync + +// An RWMutex is a reader/writer mutual exclusion lock. +// The lock can be held by an arbitrary number of readers +// or a single writer. +// RWMutexes can be created as part of other +// structures; the zero value for a RWMutex is +// an unlocked mutex. +// +// Writers take priority over Readers: no new RLocks +// are granted while a blocked Lock call is waiting. +type RWMutex struct { + w Mutex // held if there are pending readers or writers + r Mutex // held if the w is being rd + readerCount uint32 // number of pending readers +} + +// RLock locks rw for reading. +// If the lock is already locked for writing or there is a writer already waiting +// to release the lock, RLock blocks until the writer has released the lock. +func (rw *RWMutex) RLock() { + // Use rw.r.Lock() to block granting the RLock if a goroutine + // is waiting for its Lock. This is the prevent starvation of W in + // this situation: + // A: rw.RLock() // granted + // W: rw.Lock() // waiting for rw.w().Lock() + // B: rw.RLock() // granted + // C: rw.RLock() // granted + // B: rw.RUnlock() + // ... (new readers come and go indefinitely, W is starving) + rw.r.Lock() + if xadd(&rw.readerCount, 1) == 1 { + // The first reader locks rw.w, so writers will be blocked + // while the readers have the RLock. + rw.w.Lock() + } + rw.r.Unlock() +} + +// RUnlock undoes a single RLock call; +// it does not affect other simultaneous readers. +// It is a run-time error if rw is not locked for reading +// on entry to RUnlock. +func (rw *RWMutex) RUnlock() { + if xadd(&rw.readerCount, -1) == 0 { + // last reader finished, enable writers + rw.w.Unlock() + } +} + +// Lock locks rw for writing. +// If the lock is already locked for reading or writing, +// Lock blocks until the lock is available. +// To ensure that the lock eventually becomes available, +// a blocked Lock call excludes new readers from acquiring +// the lock. +func (rw *RWMutex) Lock() { + rw.r.Lock() + rw.w.Lock() + rw.r.Unlock() +} + +// Unlock unlocks rw for writing. +// It is a run-time error if rw is not locked for writing +// on entry to Unlock. +// +// Like for Mutexes, +// a locked RWMutex is not associated with a particular goroutine. +// It is allowed for one goroutine to RLock (Lock) an RWMutex and then +// arrange for another goroutine to RUnlock (Unlock) it. +func (rw *RWMutex) Unlock() { rw.w.Unlock() } |