mirror of
https://github.com/golang/go
synced 2024-11-25 14:07:56 -07:00
expand ticker interface to allow a client to shut down a ticker.
existing interface still works. R=rsc DELTA=50 (32 added, 2 deleted, 16 changed) OCL=34930 CL=34932
This commit is contained in:
parent
ea4ada89e1
commit
fbb7029747
@ -7,7 +7,7 @@ package time
|
||||
// TODO(rsc): This implementation of Tick is a
|
||||
// simple placeholder. Eventually, there will need to be
|
||||
// a single central time server no matter how many tickers
|
||||
// are active. There also needs to be a way to cancel a ticker.
|
||||
// are active.
|
||||
//
|
||||
// Also, if timeouts become part of the select statement,
|
||||
// perhaps the Ticker is just:
|
||||
@ -19,40 +19,63 @@ package time
|
||||
// c <- nsec;
|
||||
// }
|
||||
|
||||
func ticker(ns int64, c chan int64) {
|
||||
|
||||
// A Ticker holds a synchronous channel that delivers `ticks' of a clock
|
||||
// at intervals.
|
||||
type Ticker struct {
|
||||
C <-chan int64; // The channel on which the ticks are delivered.
|
||||
ns int64;
|
||||
shutdown bool;
|
||||
}
|
||||
|
||||
// Stop turns off a ticker. After Stop, no more ticks will be delivered.
|
||||
func (t *Ticker) Stop() {
|
||||
t.shutdown = true
|
||||
}
|
||||
|
||||
func (t *Ticker) ticker(c chan<- int64) {
|
||||
now := Nanoseconds();
|
||||
when := now;
|
||||
for {
|
||||
when += ns; // next alarm
|
||||
for !t.shutdown {
|
||||
when += t.ns; // next alarm
|
||||
|
||||
// if c <- now took too long, skip ahead
|
||||
if when < now {
|
||||
// one big step
|
||||
when += (now-when)/ns * ns;
|
||||
when += (now-when)/t.ns * t.ns;
|
||||
}
|
||||
for when <= now {
|
||||
// little steps until when > now
|
||||
when += ns
|
||||
when += t.ns
|
||||
}
|
||||
|
||||
Sleep(when - now);
|
||||
now = Nanoseconds();
|
||||
c <- now;
|
||||
if closed(c) {
|
||||
if t.shutdown {
|
||||
return;
|
||||
}
|
||||
c <- now;
|
||||
}
|
||||
}
|
||||
|
||||
// Tick creates a synchronous channel that will send the time, in nanoseconds,
|
||||
// every ns nanoseconds. It adjusts the intervals to make up for pauses in
|
||||
// delivery of the ticks.
|
||||
func Tick(ns int64) chan int64 {
|
||||
// Tick is a convenience wrapper for NewTicker providing access to the ticking
|
||||
// channel only. Useful for clients that have no need to shut down the ticker.
|
||||
func Tick(ns int64) <-chan int64 {
|
||||
if ns <= 0 {
|
||||
return nil
|
||||
}
|
||||
return NewTicker(ns).C;
|
||||
}
|
||||
|
||||
// Ticker returns a new Ticker containing a synchronous channel that will
|
||||
// send the time, in nanoseconds, every ns nanoseconds. It adjusts the
|
||||
// intervals to make up for pauses in delivery of the ticks.
|
||||
func NewTicker(ns int64) *Ticker {
|
||||
if ns <= 0 {
|
||||
return nil
|
||||
}
|
||||
c := make(chan int64);
|
||||
go ticker(ns, c);
|
||||
return c;
|
||||
t := &Ticker{c, ns, false};
|
||||
go t.ticker(c);
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -9,16 +9,17 @@ import (
|
||||
. "time";
|
||||
)
|
||||
|
||||
func TestTick(t *testing.T) {
|
||||
func TestTicker(t *testing.T) {
|
||||
const (
|
||||
Delta = 100*1e6;
|
||||
Count = 10;
|
||||
);
|
||||
c := Tick(Delta);
|
||||
ticker := NewTicker(Delta);
|
||||
t0 := Nanoseconds();
|
||||
for i := 0; i < Count; i++ {
|
||||
<-c;
|
||||
<-ticker.C;
|
||||
}
|
||||
ticker.Stop();
|
||||
t1 := Nanoseconds();
|
||||
ns := t1 - t0;
|
||||
target := int64(Delta*Count);
|
||||
@ -26,4 +27,10 @@ func TestTick(t *testing.T) {
|
||||
if ns < target - slop || ns > target + slop {
|
||||
t.Fatalf("%d ticks of %g ns took %g ns, expected %g", Count, float64(Delta), float64(ns), float64(target));
|
||||
}
|
||||
// Now test that the ticker stopped
|
||||
Sleep(2*Delta);
|
||||
_, received := <-ticker.C;
|
||||
if received {
|
||||
t.Fatalf("Ticker did not shut down");
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user