context.go 828 B

123456789101112131415161718192021222324252627282930313233343536373839
  1. package stmutil
  2. import (
  3. "context"
  4. "sync"
  5. "github.com/anacrolix/stm"
  6. )
  7. var (
  8. mu sync.Mutex
  9. ctxVars = map[context.Context]*stm.Var[bool]{}
  10. )
  11. // Returns an STM var that contains a bool equal to `ctx.Err != nil`, and a cancel function to be
  12. // called when the user is no longer interested in the var.
  13. func ContextDoneVar(ctx context.Context) (*stm.Var[bool], func()) {
  14. mu.Lock()
  15. defer mu.Unlock()
  16. if v, ok := ctxVars[ctx]; ok {
  17. return v, func() {}
  18. }
  19. if ctx.Err() != nil {
  20. // TODO: What if we had read-only Vars? Then we could have a global one for this that we
  21. // just reuse.
  22. v := stm.NewBuiltinEqVar(true)
  23. return v, func() {}
  24. }
  25. v := stm.NewVar(false)
  26. go func() {
  27. <-ctx.Done()
  28. stm.AtomicSet(v, true)
  29. mu.Lock()
  30. delete(ctxVars, ctx)
  31. mu.Unlock()
  32. }()
  33. ctxVars[ctx] = v
  34. return v, func() {}
  35. }