1//  Copyright (c) 2017 Couchbase, Inc.
2//
3//  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
4//  except in compliance with the License. You may obtain a copy of the License at
5//    http://www.apache.org/licenses/LICENSE-2.0
6//  Unless required by applicable law or agreed to in writing, software distributed under the
7//  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
8//  either express or implied. See the License for the specific language governing permissions
9//  and limitations under the License.
10
11package util
12
13// We implement here sync types that in sync don't do exactly what we want.
14// Our implementation tends to be leaner too.
15
16import (
17	atomic "github.com/couchbase/go-couchbase/platform"
18)
19
20// Once is an object that will perform exactly one action.
21type Once struct {
22	done uint32
23}
24
25// Do calls the function f if and only if Do is being called for the
26// first time for this instance of Once. In other words, given
27// 	var once Once
28// if once.Do(f) is called multiple times, only the first call will invoke f,
29// even if f has a different value in each invocation. A new instance of
30// Once is required for each function to execute.
31//
32// Do is intended for initialization that must be run exactly once. Since f
33// is niladic, it may be necessary to use a function literal to capture the
34// arguments to a function to be invoked by Do:
35// 	config.once.Do(func() { config.init(filename) })
36//
37// Because no call to Do returns until the one call to f returns, if f causes
38// Do to be called, it will deadlock.
39//
40// If f panics, Do considers it to have returned; future calls of Do return
41// without calling f.
42//
43// Our Once type can be reset
44func (o *Once) Do(f func()) {
45	if atomic.LoadUint32(&o.done) > 0 {
46		return
47	}
48
49	// Slow-path.
50	if atomic.AddUint32(&o.done, 1) == 1 {
51		f()
52	}
53}
54
55func (o *Once) Reset() {
56	atomic.StoreUint32(&o.done, 0)
57}
58