forked from ebhomengo/niki
1
0
Fork 0
niki/vendor/github.com/redis/go-redis/v9/internal/once.go

113 lines
1.8 KiB
Go
Raw Normal View History

2024-02-18 10:42:21 +00:00
/*
2024-02-18 10:42:21 +00:00
Copyright 2014 The Camlistore Authors
2024-02-18 10:42:21 +00:00
Licensed under the Apache License, Version 2.0 (the "License");
2024-02-18 10:42:21 +00:00
you may not use this file except in compliance with the License.
2024-02-18 10:42:21 +00:00
You may obtain a copy of the License at
2024-02-18 10:42:21 +00:00
http://www.apache.org/licenses/LICENSE-2.0
2024-02-18 10:42:21 +00:00
Unless required by applicable law or agreed to in writing, software
2024-02-18 10:42:21 +00:00
distributed under the License is distributed on an "AS IS" BASIS,
2024-02-18 10:42:21 +00:00
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
2024-02-18 10:42:21 +00:00
See the License for the specific language governing permissions and
2024-02-18 10:42:21 +00:00
limitations under the License.
2024-02-18 10:42:21 +00:00
*/
package internal
import (
"sync"
"sync/atomic"
)
// A Once will perform a successful action exactly once.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// Unlike a sync.Once, this Once's func returns an error
2024-02-18 10:42:21 +00:00
// and is re-armed on failure.
2024-02-18 10:42:21 +00:00
type Once struct {
m sync.Mutex
2024-02-18 10:42:21 +00:00
done uint32
}
// Do calls the function f if and only if Do has not been invoked
2024-02-18 10:42:21 +00:00
// without error for this instance of Once. In other words, given
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// var once Once
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// if once.Do(f) is called multiple times, only the first call will
2024-02-18 10:42:21 +00:00
// invoke f, even if f has a different value in each invocation unless
2024-02-18 10:42:21 +00:00
// f returns an error. A new instance of Once is required for each
2024-02-18 10:42:21 +00:00
// function to execute.
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// Do is intended for initialization that must be run exactly once. Since f
2024-02-18 10:42:21 +00:00
// is niladic, it may be necessary to use a function literal to capture the
2024-02-18 10:42:21 +00:00
// arguments to a function to be invoked by Do:
2024-02-18 10:42:21 +00:00
//
2024-02-18 10:42:21 +00:00
// err := config.once.Do(func() error { return config.init(filename) })
2024-02-18 10:42:21 +00:00
func (o *Once) Do(f func() error) error {
2024-02-18 10:42:21 +00:00
if atomic.LoadUint32(&o.done) == 1 {
2024-02-18 10:42:21 +00:00
return nil
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
// Slow-path.
2024-02-18 10:42:21 +00:00
o.m.Lock()
2024-02-18 10:42:21 +00:00
defer o.m.Unlock()
2024-02-18 10:42:21 +00:00
var err error
2024-02-18 10:42:21 +00:00
if o.done == 0 {
2024-02-18 10:42:21 +00:00
err = f()
2024-02-18 10:42:21 +00:00
if err == nil {
2024-02-18 10:42:21 +00:00
atomic.StoreUint32(&o.done, 1)
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
}
2024-02-18 10:42:21 +00:00
return err
2024-02-18 10:42:21 +00:00
}