Is it possible in some easy way to do the equivalent of Java's
wait(long timeMillis)
which waits on a monitor (mutex+cond, roughly) for a specified amount of time, and returns if it is not signalled?
I can't find anything in the docs or googling around on this, and although it's of course possible to play some games with making a WaitGroup and having a timer goroutine pop, that seems tedious/annoying/inefficient to just get this simple functionality (which is by the way directly supported by any underlying systems thread library I've ever encountered)
Edit: Yes we have all read http://www.golang-book.com/10/index.htm as well as https://blog.golang.org/pipelines - again, creating more threads is a "bad" (non-performant) solution to this, and channels are also not well suited to this. Imagine for a use case a typical concurrent server Join() method... (Please do not tell me to invert the control and use a Listener pattern instead. You don't always have the luxury to change the API you are working with...)
I sketched out a couple of possible alternatives in my GopherCon talk this year (see https://drive.google.com/file/d/1nPdvhB0PutEJzdCq5ms6UI58dp50fcAN/view). The “Condition Variables” section starts at slide 37, but this particular pattern is covered in more detail in the backup slides (101-105).
As zviadm notes, one option (https://play.golang.org/p/tWVvXOs87HX) is to close a channel.
Another option (https://play.golang.org/p/uRwV_i0v13T) is to have each waiter allocate a 1-buffered channel, and have the broadcaster send a token into the buffer to broadcast.
If the event is a persistent condition, such as “the queue is empty”, a third option (https://play.golang.org/p/uvx8vFSQ2f0) is to use a 1-buffered channel and have each receiver refill the buffer as long as the condition persists.
https://gitlab.com/jonas.jasas/condchan makes it possible to timeout on wait. Please see an example:
package main
import (
"fmt"
"sync"
"time"
"gitlab.com/jonas.jasas/condchan"
)
func main() {
cc := condchan.New(&sync.Mutex{})
timeoutChan := time.After(time.Second)
cc.L.Lock()
// Passing func that gets channel c that signals when
// Signal or Broadcast is called on CondChan
cc.Select(func(c <-chan struct{}) { // Waiting with select
select {
case <-c: // Never ending wait
case <-timeoutChan:
fmt.Println("Hooray! Just escaped from eternal wait.")
}
})
cc.L.Unlock()
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With