1
0
mirror of https://github.com/golang/go synced 2024-10-04 13:21:22 -06:00
go/src/pkg/sync/rwmutex.go
Robert Griesemer d65a5cce89 1) Change default gofmt default settings for
parsing and printing to new syntax.

   Use -oldparser to parse the old syntax,
   use -oldprinter to print the old syntax.

2) Change default gofmt formatting settings
   to use tabs for indentation only and to use
   spaces for alignment. This will make the code
   alignment insensitive to an editor's tabwidth.

   Use -spaces=false to use tabs for alignment.

3) Manually changed src/exp/parser/parser_test.go
   so that it doesn't try to parse the parser's
   source files using the old syntax (they have
   new syntax now).

4) gofmt -w src misc test/bench

4th set of files.

R=rsc
CC=golang-dev
https://golang.org/cl/180049
2009-12-15 15:40:16 -08:00

76 lines
2.5 KiB
Go

// 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 r 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() }