1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
9 // An RWMutex is a reader/writer mutual exclusion lock.
10 // The lock can be held by an arbitrary number of readers
11 // or a single writer.
12 // RWMutexes can be created as part of other
13 // structures; the zero value for a RWMutex is
16 w Mutex
// held if there are pending writers
17 writerSem
uint32 // semaphore for writers to wait for completing readers
18 readerSem
uint32 // semaphore for readers to wait for completing writers
19 readerCount
int32 // number of pending readers
20 readerWait
int32 // number of departing readers
23 const rwmutexMaxReaders
= 1 << 30
25 // RLock locks rw for reading.
26 func (rw
*RWMutex
) RLock() {
27 if atomic
.AddInt32(&rw
.readerCount
, 1) < 0 {
28 // A writer is pending, wait for it.
29 runtime_Semacquire(&rw
.readerSem
)
33 // RUnlock undoes a single RLock call;
34 // it does not affect other simultaneous readers.
35 // It is a run-time error if rw is not locked for reading
36 // on entry to RUnlock.
37 func (rw
*RWMutex
) RUnlock() {
38 if atomic
.AddInt32(&rw
.readerCount
, -1) < 0 {
39 // A writer is pending.
40 if atomic
.AddInt32(&rw
.readerWait
, -1) == 0 {
41 // The last reader unblocks the writer.
42 runtime_Semrelease(&rw
.writerSem
)
47 // Lock locks rw for writing.
48 // If the lock is already locked for reading or writing,
49 // Lock blocks until the lock is available.
50 // To ensure that the lock eventually becomes available,
51 // a blocked Lock call excludes new readers from acquiring
53 func (rw
*RWMutex
) Lock() {
54 // First, resolve competition with other writers.
56 // Announce to readers there is a pending writer.
57 r
:= atomic
.AddInt32(&rw
.readerCount
, -rwmutexMaxReaders
) + rwmutexMaxReaders
58 // Wait for active readers.
59 if r
!= 0 && atomic
.AddInt32(&rw
.readerWait
, r
) != 0 {
60 runtime_Semacquire(&rw
.writerSem
)
64 // Unlock unlocks rw for writing. It is a run-time error if rw is
65 // not locked for writing on entry to Unlock.
67 // As with Mutexes, a locked RWMutex is not associated with a particular
68 // goroutine. One goroutine may RLock (Lock) an RWMutex and then
69 // arrange for another goroutine to RUnlock (Unlock) it.
70 func (rw
*RWMutex
) Unlock() {
71 // Announce to readers there is no active writer.
72 r
:= atomic
.AddInt32(&rw
.readerCount
, rwmutexMaxReaders
)
73 // Unblock blocked readers, if any.
74 for i
:= 0; i
< int(r
); i
++ {
75 runtime_Semrelease(&rw
.readerSem
)
77 // Allow other writers to proceed.
81 // RLocker returns a Locker interface that implements
82 // the Lock and Unlock methods by calling rw.RLock and rw.RUnlock.
83 func (rw
*RWMutex
) RLocker() Locker
{
89 func (r
*rlocker
) Lock() { (*RWMutex
)(r
).RLock() }
90 func (r
*rlocker
) Unlock() { (*RWMutex
)(r
).RUnlock() }