Reputation: 5886
I want to only proceed with my execution when a certain channel blocks waiting for data to come (the blocking channel is part of a working go routine, supposed to run in parallel).
Like:
func foo(c chan bool) {
go start_blocking(c)
// only come here, when channel c actually blocks!
}
func start_blocking(c chan bool) {
<-c
}
How to achieve this?
Purpose:
The channel is waiting for data to come at some time later and it should be ready in the background, before the main execution continues.
Upvotes: 2
Views: 5381
Reputation: 66354
Channels don't block; it's communications (send or receive) on them that may block.
Checking whether a channel communication would block without actually attempting the communication in question is not very idiomatic in Go, for reasons discussed below. However, if that's really what you want, you could do the following. For a given (buffered!) channel ch
, you could
len(ch) == cap(ch)
to determine whether a send would block;len(ch) == 0
to determine whether a receive would block.However, both checks are likely to become stale very quickly, because another goroutine may have sent to or received from the channel shortly after your check; a classic instance of time-of-check to time-of-use (TOCTOU).
And as pointed out in the comments, one caveat of this approach is that it doesn't work for unbuffered channels, for which the two conditions invariably evaluate to true
.
Upvotes: 4
Reputation: 418337
You can't "peek" a channel without actually receiving from it. So channels are not a good tool if you really need this functionality. If you have a buffered channel, you can of course check if there's a value in its buffer by checking its length (len(ch)
), but there's no guarantee the value can still be received if you attempt to do it afterwards.
If you do need this functionality, use a counter instead with atomic reads and writes. It is possible to read a counter's value without decrementing it.
And if you do need a channel, using a select
with default
case should suffice: you may do non-blocking send and receive, and if a send or receive would block, the default
case will be executed without blocking.
Upvotes: 5