// Copyright 2009 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// This package provides a single function, Do, to run a function
// exactly once, usually used as part of initialization.
package once
import "sync"
type job struct {
done bool;
sync.Mutex; // should probably be sync.Notification or some such
}
var jobs = make(map[func()]*job)
var joblock sync.Mutex
// Do is the the only exported piece of the package.
// For one-time initialization that is not done during init,
// wrap the initialization in a niladic function f() and call
// Do(f)
// If multiple processes call Do(f) simultaneously
// with the same f argument, only one will call f, and the
// others will block until f finishes running.
//
// Since a func() expression typically evaluates to a differerent
// function value each time it is evaluated, it is incorrect to
// pass such values to Do. For example,
// func f(x int) {
// Do(func() { fmt.Println(x) })
// }
// behaves the same as
// func f(x int) {
// fmt.Println(x)
// }
// because the func() expression in the first creates a new
// func each time f runs, and each of those funcs is run once.
func Do(f func()) {
joblock.Lock();
j, present := jobs[f];
if !present {
// run it
j = new(job);
j.Lock();
jobs[f] = j;
joblock.Unlock();
f();
j.done = true;
j.Unlock();
} else {
// wait for it
joblock.Unlock();
if j.done != true {
j.Lock();
j.Unlock();
}
}
}
|