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