Peeks goroutines and helps gophers cope with those in intuitive ways such as waiting for some goroutines to change its state into waiting a lock primitive and so on.
It is mostly useful on test code now using time.Sleep to yield other goroutines a moment to make something happen. Such tests tend to take long if time.Sleep invoked many times. With gopeek you can do within the order of magnitude less time.
uber-go/ratelimit#1 (diff) motivated me solve this problem in a generalized way.
import "github.com/cat2neat/gopeek"
import "github.com/maruel/panicparse/stack"
// Wait for goroutines
// - created by a func that matches "gopeek_test.TestGoPeek.*" (Regex can be used)
// - locked at a M (Any fields in stack.Gorotine can be used at user-defined)
// - blocked by channel primitives
// - the number of goroutines which satisfy the above conditions == 3
// Return goroutines that satisfy the above all conditions or
// Timeout after time.Millisecond passed if no goroutines satisfy.
gopeek.NewCondition().
CreatedBy("gopeek_test.TestGoPeek.*").
FilterByGo(func(g *stack.Gorotine) bool {
return g.Signature.Locked
}).
Is(gopeek.StateWaitingChannel).
EQ(3).
Wait(time.Millisecond)
// Wait for goroutines
// - created by a func that matches "gopeek_test.TestGoPeek.*"
// - blocked by I/O (net poller) or Lock caused by sync primitives or time.Sleep
// - the number of goroutines which satisfy the above conditions == 3 or >= 6
// Return goroutines that satisfy the above all conditions or
// Timeout after time.Millisecond passed if no goroutines satisfy.
gopeek.NewCondition().
CreatedBy("gopeek_test.TestGoPeek.*").
In(gopeek.StateWaitingIO, gopeek.StateWaitingLock, gopeek.StateSleeping).
FilterByGoes(func(gs []stack.Gorotine) bool {
return len(gs) == 3 || len(gs) >= 6
}).
Wait(time.Millisecond)
go get -u github.com/cat2neat/gopeek
- Wait for goroutines to satisfy specified conditions
- Retrieve goroutines that satisfy specified conditions
with built-in filters and|or user-defined ones.
All filters are lazy evaluated when (Wait|Eval) called.
See the above example code or gopeek_test.go for the actual use.
Don't use gopeek except in test code. You should be wrong if you will try to solve a real concurrency problem with gopeek.