| // 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. | |
| 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(); | |
| } | |
| } | |
| } |