github.com/livekit/protocol@v1.39.3/utils/promise.go (about) 1 package utils 2 3 import ( 4 "context" 5 "sync" 6 ) 7 8 var closedPromiseChan = make(chan struct{}) 9 10 func init() { 11 close(closedPromiseChan) 12 } 13 14 type Promise[T any] struct { 15 mu sync.Mutex 16 done chan struct{} 17 Result T 18 Err error 19 } 20 21 func NewPromise[T any]() *Promise[T] { 22 return &Promise[T]{ 23 done: make(chan struct{}), 24 } 25 } 26 27 func GoPromise[T any](f func() (T, error)) *Promise[T] { 28 p := NewPromise[T]() 29 go func() { p.Resolve(f()) }() 30 return p 31 } 32 33 func NewResolvedPromise[T any](result T, err error) *Promise[T] { 34 return &Promise[T]{ 35 Result: result, 36 Err: err, 37 done: closedPromiseChan, 38 } 39 } 40 41 func (p *Promise[T]) Resolve(result T, err error) { 42 p.mu.Lock() 43 defer p.mu.Unlock() 44 45 if p.done == closedPromiseChan { 46 return 47 } 48 49 p.Result = result 50 p.Err = err 51 52 if p.done != nil { 53 close(p.done) 54 } 55 p.done = closedPromiseChan 56 } 57 58 func (p *Promise[T]) Done() <-chan struct{} { 59 p.mu.Lock() 60 defer p.mu.Unlock() 61 if p.done == nil { 62 p.done = make(chan struct{}) 63 } 64 return p.done 65 } 66 67 func (p *Promise[T]) Resolved() bool { 68 p.mu.Lock() 69 defer p.mu.Unlock() 70 return p.done == closedPromiseChan 71 } 72 73 func AwaitPromise[T any](ctx context.Context, p *Promise[T]) (T, error) { 74 select { 75 case <-ctx.Done(): 76 var v T 77 return v, ctx.Err() 78 case <-p.Done(): 79 return p.Result, p.Err 80 } 81 }