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  }