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 }