1 // Copyright 2011 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.
7 // Cond implements a condition variable, a rendezvous point
8 // for goroutines waiting for or announcing the occurrence
11 // Each Cond has an associated Locker L (often a *Mutex or *RWMutex),
12 // which must be held when changing the condition and
13 // when calling the Wait method.
15 L Locker
// held while observing or changing the condition
16 m Mutex
// held to avoid internal races
18 // We must be careful to make sure that when Signal
19 // releases a semaphore, the corresponding acquire is
20 // executed by a goroutine that was already waiting at
21 // the time of the call to Signal, not one that arrived later.
22 // To ensure this, we segment waiting goroutines into
23 // generations punctuated by calls to Signal. Each call to
24 // Signal begins another generation if there are no goroutines
25 // left in older generations for it to wake. Because of this
26 // optimization (only begin another generation if there
27 // are no older goroutines left), we only need to keep track
28 // of the two most recent generations, which we call old
30 oldWaiters
int // number of waiters in old generation...
31 oldSema
*uint32 // ... waiting on this semaphore
33 newWaiters
int // number of waiters in new generation...
34 newSema
*uint32 // ... waiting on this semaphore
37 // NewCond returns a new Cond with Locker l.
38 func NewCond(l Locker
) *Cond
{
42 // Wait atomically unlocks c.L and suspends execution
43 // of the calling goroutine. After later resuming execution,
44 // Wait locks c.L before returning. Unlike in other systems,
45 // Wait cannot return unless awoken by Broadcast or Signal.
47 // Because c.L is not locked when Wait first resumes, the caller
48 // typically cannot assume that the condition is true when
49 // Wait returns. Instead, the caller should Wait in a loop:
55 // ... make use of condition ...
58 func (c
*Cond
) Wait() {
61 c
.newSema
= new(uint32)
71 // Signal wakes one goroutine waiting on c, if there is any.
73 // It is allowed but not required for the caller to hold c.L
75 func (c
*Cond
) Signal() {
77 if c
.oldWaiters
== 0 && c
.newWaiters
> 0 {
78 // Retire old generation; rename new to old.
79 c
.oldWaiters
= c
.newWaiters
86 runtime_Semrelease(c
.oldSema
)
91 // Broadcast wakes all goroutines waiting on c.
93 // It is allowed but not required for the caller to hold c.L
95 func (c
*Cond
) Broadcast() {
97 // Wake both generations.
99 for i
:= 0; i
< c
.oldWaiters
; i
++ {
100 runtime_Semrelease(c
.oldSema
)
104 if c
.newWaiters
> 0 {
105 for i
:= 0; i
< c
.newWaiters
; i
++ {
106 runtime_Semrelease(c
.newSema
)