github.com/ydb-platform/ydb-go-sdk/v3@v3.89.2/internal/xsync/once.go (about)

     1  package xsync
     2  
     3  import (
     4  	"context"
     5  	"sync"
     6  
     7  	"github.com/ydb-platform/ydb-go-sdk/v3/internal/closer"
     8  )
     9  
    10  func OnceFunc(f func(ctx context.Context) error) func(ctx context.Context) error {
    11  	var once sync.Once
    12  
    13  	return func(ctx context.Context) (err error) {
    14  		once.Do(func() {
    15  			err = f(ctx)
    16  		})
    17  
    18  		return err
    19  	}
    20  }
    21  
    22  type Once[T closer.Closer] struct {
    23  	f     func() (T, error)
    24  	once  sync.Once
    25  	mutex sync.RWMutex
    26  	t     T
    27  	err   error
    28  }
    29  
    30  func OnceValue[T closer.Closer](f func() (T, error)) *Once[T] {
    31  	return &Once[T]{f: f}
    32  }
    33  
    34  func (v *Once[T]) Close(ctx context.Context) (err error) {
    35  	has := true
    36  	v.once.Do(func() {
    37  		has = false
    38  	})
    39  
    40  	if has {
    41  		v.mutex.RLock()
    42  		defer v.mutex.RUnlock()
    43  
    44  		return v.t.Close(ctx)
    45  	}
    46  
    47  	return nil
    48  }
    49  
    50  func (v *Once[T]) Get() (T, error) {
    51  	v.once.Do(func() {
    52  		v.mutex.Lock()
    53  		defer v.mutex.Unlock()
    54  
    55  		v.t, v.err = v.f()
    56  	})
    57  
    58  	v.mutex.RLock()
    59  	defer v.mutex.RUnlock()
    60  
    61  	return v.t, v.err
    62  }
    63  
    64  func (v *Once[T]) Must() T {
    65  	t, err := v.Get()
    66  	if err != nil {
    67  		panic(err)
    68  	}
    69  
    70  	return t
    71  }