...

Source file src/pkg/sync/cond.go

     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.
     4	
     5	package sync
     6	
     7	import (
     8		"sync/atomic"
     9		"unsafe"
    10	)
    11	
    12	// Cond implements a condition variable, a rendezvous point
    13	// for goroutines waiting for or announcing the occurrence
    14	// of an event.
    15	//
    16	// Each Cond has an associated Locker L (often a *Mutex or *RWMutex),
    17	// which must be held when changing the condition and
    18	// when calling the Wait method.
    19	//
    20	// A Cond must not be copied after first use.
    21	type Cond struct {
    22		noCopy noCopy
    23	
    24		// L is held while observing or changing the condition
    25		L Locker
    26	
    27		notify  notifyList
    28		checker copyChecker
    29	}
    30	
    31	// NewCond returns a new Cond with Locker l.
    32	func NewCond(l Locker) *Cond {
    33		return &Cond{L: l}
    34	}
    35	
    36	// Wait atomically unlocks c.L and suspends execution
    37	// of the calling goroutine. After later resuming execution,
    38	// Wait locks c.L before returning. Unlike in other systems,
    39	// Wait cannot return unless awoken by Broadcast or Signal.
    40	//
    41	// Because c.L is not locked when Wait first resumes, the caller
    42	// typically cannot assume that the condition is true when
    43	// Wait returns. Instead, the caller should Wait in a loop:
    44	//
    45	//    c.L.Lock()
    46	//    for !condition() {
    47	//        c.Wait()
    48	//    }
    49	//    ... make use of condition ...
    50	//    c.L.Unlock()
    51	//
    52	func (c *Cond) Wait() {
    53		c.checker.check()
    54		t := runtime_notifyListAdd(&c.notify)
    55		c.L.Unlock()
    56		runtime_notifyListWait(&c.notify, t)
    57		c.L.Lock()
    58	}
    59	
    60	// Signal wakes one goroutine waiting on c, if there is any.
    61	//
    62	// It is allowed but not required for the caller to hold c.L
    63	// during the call.
    64	func (c *Cond) Signal() {
    65		c.checker.check()
    66		runtime_notifyListNotifyOne(&c.notify)
    67	}
    68	
    69	// Broadcast wakes all goroutines waiting on c.
    70	//
    71	// It is allowed but not required for the caller to hold c.L
    72	// during the call.
    73	func (c *Cond) Broadcast() {
    74		c.checker.check()
    75		runtime_notifyListNotifyAll(&c.notify)
    76	}
    77	
    78	// copyChecker holds back pointer to itself to detect object copying.
    79	type copyChecker uintptr
    80	
    81	func (c *copyChecker) check() {
    82		if uintptr(*c) != uintptr(unsafe.Pointer(c)) &&
    83			!atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.Pointer(c))) &&
    84			uintptr(*c) != uintptr(unsafe.Pointer(c)) {
    85			panic("sync.Cond is copied")
    86		}
    87	}
    88	
    89	// noCopy may be embedded into structs which must not be copied
    90	// after the first use.
    91	//
    92	// See https://golang.org/issues/8005#issuecomment-190753527
    93	// for details.
    94	type noCopy struct{}
    95	
    96	// Lock is a no-op used by -copylocks checker from `go vet`.
    97	func (*noCopy) Lock()   {}
    98	func (*noCopy) Unlock() {}
    99	

View as plain text