-
Notifications
You must be signed in to change notification settings - Fork 18.3k
Description
In the discussion on #16620, I've noticed that the majority of use-cases folks describe for sync.Cond
turn out to work fine with a channel instead: (*sync.Cond).Broadcast
corresponds to calling close
on the channel, and (*sync.Cond).Signal
corresponds to sending on the channel.
The existence of sync.Cond
suggests that people might want to use it, but it is currently under-documented (#20491), incompatible with other Go synchronization patterns (e.g. select
statements; see #16620), and unlike most other types in the sync
package, does not have a valid zero-value (its Wait
method requires a non-nil L
field). It has an additional "no copy" invariant enforced through both a run-time dynamic check and special-case code in the vet
tool.
On top of that, condition variables are fiendishly difficult to use: they are prone to either missed or spurious signals [citation needed — experience reports welcome].
An audit of the Go standard library shows only a handful of uses:
io/pipe.go
: The use ofsync.Cond
was added in https://golang.org/cl/4252057. The previous implementation used channels and had no known bugs.syscall/net_nacl.go
: The comment there says "We do not use channels because we need to be able to handle writes after and during close, and because a chan byte would require too many send and receive operations in real use." It does not explain why these considerations preclude the use of channels (e.g. a separate 'chan struct{}' to signal closing, and channels of tokens or slices rather than channels of tokens or bytes).net/http/h2_bundle.go
: There are twosync.Cond
s in this file. One is is in a struct "likeio.Pipe
". The other is only used withBroadcast
(neverSignal
), and can thus be replaced with a channel that is closed to broadcast readiness.net/http/server.go
: Thissync.Cond
is again only used withBroadcast
, and thus easy to replace with a channel.crypto/tls/conn.go
: Again only used withBroadcast
.
Of the above uses, only the one in syscall/net_nacl.go
does not have an obvious channel equivalent. However, it appears to be used to limit the size of a buffer, and I know of at least one similar "limiter" API (x/sync/semaphore
) that is implemented in terms of channels in order to support interoperation with the standard context
package. (I did the Cond
-to-channel conversion myself on a prototype of that package before it was open-sourced.)
In light of the above observations, I propose that we remove the Cond
type from the sync
package in Go 2.