summaryrefslogtreecommitdiff
path: root/libgo/go/sync/rwmutex.go
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libgo/go/sync/rwmutex.go
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.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.go75
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() }