// Copyright 2026 The Gitea Authors. All rights reserved. // SPDX-License-Identifier: MIT package util import ( "sync" "sync/atomic" ) type onceValueResult[T any] struct { value T panic any } // OnceValue is similar to Golang's "sync.OnceValue", but can be reset. type OnceValue[T any] struct { Func func() T mu sync.Mutex res atomic.Pointer[onceValueResult[T]] } func (o *OnceValue[T]) Value() T { res := o.res.Load() if res == nil { o.mu.Lock() defer o.mu.Unlock() res = o.res.Load() if res == nil { res = &onceValueResult[T]{} defer func() { res.panic = recover() o.res.Store(res) if res.panic != nil { panic(res.panic) } }() res.value = o.Func() } } if res.panic != nil { panic(res.panic) } return res.value } func (o *OnceValue[T]) Reset() { o.mu.Lock() defer o.mu.Unlock() o.res.Store(nil) }