Commit 3c17ee69 authored by Russ Cox's avatar Russ Cox

add "once" package

R=r
DELTA=79  (79 added, 0 deleted, 0 changed)
OCL=15656
CL=15656
parent 173ca8a2
...@@ -25,6 +25,7 @@ for i in \ ...@@ -25,6 +25,7 @@ for i in \
io.go\ io.go\
bufio.go\ bufio.go\
strings.go\ strings.go\
once.go\
do do
base=$(basename $i .go) base=$(basename $i .go)
......
// 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.
// For one-time initialization that is not done during init.
// Wrap the initialization in a niladic function f() and call
// once.Do(&f)
// If multiple processes call once.Do(&f) simultaneously
// with the same f argument, only one will call f, and the
// others will block until f finishes running.
package once
type Job struct {
done bool;
doit *chan bool; // buffer of 1
}
type Request struct {
f *();
reply *chan *Job
}
// TODO: Would like to use chan Request but 6g rejects it.
var service = new(chan *Request)
var jobmap = new(map[*()]*Job)
// Moderate access to the jobmap.
// Even if accesses were thread-safe (they should be but are not)
// something needs to serialize creation of new jobs.
// That's what the Server does.
func Server() {
for {
req := <-service;
job, present := jobmap[req.f]
if !present {
job = new(Job);
job.doit = new(chan bool, 1);
job.doit <- true;
jobmap[req.f] = job
}
req.reply <- job
}
}
export func Do(f *()) {
// Look for job in map (avoids channel communication).
// If not there, ask map server to make one.
// TODO: Uncomment use of jobmap[f] once
// maps are thread-safe.
var job *Job
var present bool
// job, present = jobmap[f]
if !present {
c := new(chan *Job);
req := Request{f, c};
service <- &req;
job = <-c
}
// Optimization
if job.done {
return
}
// If we're the first one, job.doit has a true waiting.
if <-job.doit {
f();
job.done = true
}
// Leave a false waiting for the next guy.
job.doit <- false
}
func init() {
go Server()
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment