LEFT | RIGHT |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package sync | 5 package sync |
6 | 6 |
7 import ( | 7 import ( |
8 "sync/atomic" | 8 "sync/atomic" |
9 "unsafe" | 9 "unsafe" |
10 ) | 10 ) |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 c.L.Unlock() | 61 c.L.Unlock() |
62 runtime_Syncsemacquire(&c.sema) | 62 runtime_Syncsemacquire(&c.sema) |
63 c.L.Lock() | 63 c.L.Lock() |
64 } | 64 } |
65 | 65 |
66 // Signal wakes one goroutine waiting on c, if there is any. | 66 // Signal wakes one goroutine waiting on c, if there is any. |
67 // | 67 // |
68 // It is allowed but not required for the caller to hold c.L | 68 // It is allowed but not required for the caller to hold c.L |
69 // during the call. | 69 // during the call. |
70 func (c *Cond) Signal() { | 70 func (c *Cond) Signal() { |
71 » c.checker.check() | 71 » c.signalImpl(false) |
72 » if raceenabled { | |
73 » » raceDisable() | |
74 » } | |
75 » for { | |
76 » » w := atomic.LoadUint32(&c.waiters) | |
77 » » if w == 0 { | |
78 » » » if raceenabled { | |
79 » » » » raceEnable() | |
80 » » » } | |
81 » » » return | |
82 » » } | |
83 » » if atomic.CompareAndSwapUint32(&c.waiters, w, w-1) { | |
84 » » » if raceenabled { | |
85 » » » » raceEnable() | |
86 » » » } | |
87 » » » break | |
88 » » } | |
89 » } | |
90 » runtime_Syncsemrelease(&c.sema, 1) | |
91 } | 72 } |
92 | 73 |
93 // Broadcast wakes all goroutines waiting on c. | 74 // Broadcast wakes all goroutines waiting on c. |
94 // | 75 // |
95 // It is allowed but not required for the caller to hold c.L | 76 // It is allowed but not required for the caller to hold c.L |
96 // during the call. | 77 // during the call. |
97 func (c *Cond) Broadcast() { | 78 func (c *Cond) Broadcast() { |
| 79 c.signalImpl(true) |
| 80 } |
| 81 |
| 82 func (c *Cond) signalImpl(all bool) { |
98 c.checker.check() | 83 c.checker.check() |
99 if raceenabled { | 84 if raceenabled { |
100 raceDisable() | 85 raceDisable() |
101 } | 86 } |
102 var w uint32 | |
103 for { | 87 for { |
104 » » w = atomic.LoadUint32(&c.waiters) | 88 » » old := atomic.LoadUint32(&c.waiters) |
105 » » if w == 0 { | 89 » » if old == 0 { |
106 if raceenabled { | 90 if raceenabled { |
107 raceEnable() | 91 raceEnable() |
108 } | 92 } |
109 return | 93 return |
110 } | 94 } |
111 » » if atomic.CompareAndSwapUint32(&c.waiters, w, 0) { | 95 » » new := old - 1 |
| 96 » » if all { |
| 97 » » » new = 0 |
| 98 » » } |
| 99 » » if atomic.CompareAndSwapUint32(&c.waiters, old, new) { |
112 if raceenabled { | 100 if raceenabled { |
113 raceEnable() | 101 raceEnable() |
114 } | 102 } |
115 » » » break | 103 » » » runtime_Syncsemrelease(&c.sema, old-new) |
| 104 » » » return |
116 } | 105 } |
117 } | 106 } |
118 runtime_Syncsemrelease(&c.sema, w) | |
119 } | 107 } |
120 | 108 |
121 // copyChecker holds back pointer to itself to detect object copying. | 109 // copyChecker holds back pointer to itself to detect object copying. |
122 type copyChecker uintptr | 110 type copyChecker uintptr |
123 | 111 |
124 func (c *copyChecker) check() { | 112 func (c *copyChecker) check() { |
125 println("check", c, *c) | |
126 if uintptr(*c) != uintptr(unsafe.Pointer(c)) && | 113 if uintptr(*c) != uintptr(unsafe.Pointer(c)) && |
127 !atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.P
ointer(c))) && | 114 !atomic.CompareAndSwapUintptr((*uintptr)(c), 0, uintptr(unsafe.P
ointer(c))) && |
128 uintptr(*c) != uintptr(unsafe.Pointer(c)) { | 115 uintptr(*c) != uintptr(unsafe.Pointer(c)) { |
129 panic("sync.Cond is copied") | 116 panic("sync.Cond is copied") |
130 } | 117 } |
131 } | 118 } |
LEFT | RIGHT |