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
diff --git a/src/pkg/time/tick.go b/src/pkg/time/tick.go
index e716ba5..b664077 100644
--- a/src/pkg/time/tick.go
+++ b/src/pkg/time/tick.go
@@ -7,7 +7,7 @@
 // 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 @@
 //			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;
 }
-