Reputation: 328
I have a question similar to How to stop a goroutine with a small twist. I don't know for sure if the goroutine is running.
var quit = make(chan bool)
func f1() {
go func() {
t := time.NewTimer(time.Minute)
select {
case <-t.C:
// Do stuff
case <-quit:
return
}
}()
}
func f2() {
quit <- true
}
If f2()
is called less than a minute after f1()
, then the goroutine returns. However, if it is called later than one minute, the goroutine will have already returned and f2()
would block.
I want f2()
to cancel the goroutine if it is running and do nothing otherwise.
What I'm trying to achieve here is to perform a task if and only if it is not canceled within a minute of creation.
Clarifications:
f2()
from being called more than once.f1()
will make sure that it's not called more than once per minute.Upvotes: 2
Views: 3266
Reputation: 8395
You can give the channel a buffer size of 1. This means you can send one value to it without blocking, even if that value is not received right away (or at all).
var quit = make(chan bool, 1)
I think the top answer is better, this is just another solution that could translate to other situations.
Upvotes: -1
Reputation: 573
Use contexts.
Run f1
with the context which may be cancelled.
Run f2
with the associated cancellation function.
func f1(ctx context.Context) {
go func(ctx context.Context) {
t := time.NewTimer(time.Minute)
select {
case <-t.C:
// Do stuff
case <-ctx.Done():
return
}
}(ctx)
}
func f2(cancel context.CancelFunc) {
cancel()
}
And later, to coordinate the two functions, you would do this:
ctx, cancel := context.WithCancel(context.Background())
f1(ctx)
f2(cancel)
You can also experiment with the context.WithTimeout
function to incorporate externally-defined timeouts.
In the case where you don't know whether there is a goroutine running already, you can initialize the ctx
and cancel
variables like above, but don't pass them into anything. This avoids having to check for nil
.
Remember to treat ctx and cancel as variables to be copied, not as references, because you don't want multiple goroutines to share memory - that may cause a race condition.
Upvotes: 10