Skip to content

Instantly share code, notes, and snippets.

@iand
Created June 18, 2012 12:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iand/2948220 to your computer and use it in GitHub Desktop.
Save iand/2948220 to your computer and use it in GitHub Desktop.
A data item that automatically saves data at a maximum rate of once every second, even if the data is changing much faster than that.
// A data item that automatically saves data at a maximum rate of once every second,
// even if the data is changing much faster than that.
// I didn't write this code. It was created by Roger Peppe and sent to the
// go-nuts mailing list. The original version is at http://play.golang.org/p/1LCxri0EXz
package main
import (
"io/ioutil"
"log"
"sync"
"time"
)
func main() {
d := NewData()
d.Set("a")
d.Set("b")
time.Sleep(250 * time.Millisecond)
d.Set("c")
time.Sleep(1000 * time.Millisecond)
d.Set("d")
time.Sleep(1100 * time.Millisecond)
}
type Data struct {
mu sync.Mutex
changed chan struct{}
s string
}
func NewData() *Data {
d := &Data{
changed: make(chan struct{}, 1),
}
go d.saver()
return d
}
func (d *Data) Set(s string) {
d.mu.Lock()
defer d.mu.Unlock()
d.s = s
select {
case d.changed <- struct{}{}:
default:
}
}
func (d *Data) Get() string {
d.mu.Lock()
defer d.mu.Unlock()
return d.s
}
func (d *Data) saver() {
for {
<-d.changed
timeout := time.After(1 * time.Second)
wait:
for {
select {
case <-d.changed:
case <-timeout:
s := d.Get()
if err := ioutil.WriteFile("/tmp/saved_data", []byte(s), 0666); err != nil {
log.Printf("failed to saved data: %v", err)
} else {
log.Printf("saved %q", s)
}
break wait
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment