minio/internal/once/singleton.go
Klaus Post f1302c40fe
Fix uninitialized replication stats (#20260)
Services are unfrozen before `initBackgroundReplication` is finished. This means that 
the globalReplicationStats write is racy. Switch to an atomic pointer.

Provide the `ReplicationPool` with the stats, so it doesn't have to be grabbed 
from the atomic pointer on every use.

All other loads and checks are nil, and calls return empty values when stats 
still haven't been initialized.
2024-08-15 05:04:40 -07:00

47 lines
952 B
Go

package once
// Singleton contains a pointer to T that must be set once.
// Until the value is set all Get() calls will block.
type Singleton[T any] struct {
v *T
set chan struct{}
}
// NewSingleton creates a new unset singleton.
func NewSingleton[T any]() *Singleton[T] {
return &Singleton[T]{set: make(chan struct{}), v: nil}
}
// Get will return the singleton value.
func (s *Singleton[T]) Get() *T {
<-s.set
return s.v
}
// GetNonBlocking will return the singleton value or nil if not set yet.
func (s *Singleton[T]) GetNonBlocking() *T {
select {
case <-s.set:
return s.v
default:
return nil
}
}
// IsSet will return whether the singleton has been set.
func (s *Singleton[T]) IsSet() bool {
select {
case <-s.set:
return true
default:
return false
}
}
// Set the value and unblock all Get requests.
// This may only be called once, a second call will panic.
func (s *Singleton[T]) Set(v *T) {
s.v = v
close(s.set)
}