Home | History | Annotate | Download | only in time
      1 // Copyright 2009 The Go Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style
      3 // license that can be found in the LICENSE file.
      4 
      5 package time
      6 
      7 // Sleep pauses the current goroutine for at least the duration d.
      8 // A negative or zero duration causes Sleep to return immediately.
      9 func Sleep(d Duration)
     10 
     11 // runtimeNano returns the current value of the runtime clock in nanoseconds.
     12 func runtimeNano() int64
     13 
     14 // Interface to timers implemented in package runtime.
     15 // Must be in sync with ../runtime/time.go:/^type timer
     16 type runtimeTimer struct {
     17 	i      int
     18 	when   int64
     19 	period int64
     20 	f      func(interface{}, uintptr) // NOTE: must not be closure
     21 	arg    interface{}
     22 	seq    uintptr
     23 }
     24 
     25 // when is a helper function for setting the 'when' field of a runtimeTimer.
     26 // It returns what the time will be, in nanoseconds, Duration d in the future.
     27 // If d is negative, it is ignored. If the returned value would be less than
     28 // zero because of an overflow, MaxInt64 is returned.
     29 func when(d Duration) int64 {
     30 	if d <= 0 {
     31 		return runtimeNano()
     32 	}
     33 	t := runtimeNano() + int64(d)
     34 	if t < 0 {
     35 		t = 1<<63 - 1 // math.MaxInt64
     36 	}
     37 	return t
     38 }
     39 
     40 func startTimer(*runtimeTimer)
     41 func stopTimer(*runtimeTimer) bool
     42 
     43 // The Timer type represents a single event.
     44 // When the Timer expires, the current time will be sent on C,
     45 // unless the Timer was created by AfterFunc.
     46 // A Timer must be created with NewTimer or AfterFunc.
     47 type Timer struct {
     48 	C <-chan Time
     49 	r runtimeTimer
     50 }
     51 
     52 // Stop prevents the Timer from firing.
     53 // It returns true if the call stops the timer, false if the timer has already
     54 // expired or been stopped.
     55 // Stop does not close the channel, to prevent a read from the channel succeeding
     56 // incorrectly.
     57 //
     58 // To prevent a timer created with NewTimer from firing after a call to Stop,
     59 // check the return value and drain the channel.
     60 // For example, assuming the program has not received from t.C already:
     61 //
     62 // 	if !t.Stop() {
     63 // 		<-t.C
     64 // 	}
     65 //
     66 // This cannot be done concurrent to other receives from the Timer's
     67 // channel.
     68 //
     69 // For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
     70 // has already expired and the function f has been started in its own goroutine;
     71 // Stop does not wait for f to complete before returning.
     72 // If the caller needs to know whether f is completed, it must coordinate
     73 // with f explicitly.
     74 func (t *Timer) Stop() bool {
     75 	if t.r.f == nil {
     76 		panic("time: Stop called on uninitialized Timer")
     77 	}
     78 	return stopTimer(&t.r)
     79 }
     80 
     81 // NewTimer creates a new Timer that will send
     82 // the current time on its channel after at least duration d.
     83 func NewTimer(d Duration) *Timer {
     84 	c := make(chan Time, 1)
     85 	t := &Timer{
     86 		C: c,
     87 		r: runtimeTimer{
     88 			when: when(d),
     89 			f:    sendTime,
     90 			arg:  c,
     91 		},
     92 	}
     93 	startTimer(&t.r)
     94 	return t
     95 }
     96 
     97 // Reset changes the timer to expire after duration d.
     98 // It returns true if the timer had been active, false if the timer had
     99 // expired or been stopped.
    100 //
    101 // Resetting a timer must take care not to race with the send into t.C
    102 // that happens when the current timer expires.
    103 // If a program has already received a value from t.C, the timer is known
    104 // to have expired, and t.Reset can be used directly.
    105 // If a program has not yet received a value from t.C, however,
    106 // the timer must be stopped andif Stop reports that the timer expired
    107 // before being stoppedthe channel explicitly drained:
    108 //
    109 // 	if !t.Stop() {
    110 // 		<-t.C
    111 // 	}
    112 // 	t.Reset(d)
    113 //
    114 // This should not be done concurrent to other receives from the Timer's
    115 // channel.
    116 //
    117 // Note that it is not possible to use Reset's return value correctly, as there
    118 // is a race condition between draining the channel and the new timer expiring.
    119 // Reset should always be invoked on stopped or expired channels, as described above.
    120 // The return value exists to preserve compatibility with existing programs.
    121 func (t *Timer) Reset(d Duration) bool {
    122 	if t.r.f == nil {
    123 		panic("time: Reset called on uninitialized Timer")
    124 	}
    125 	w := when(d)
    126 	active := stopTimer(&t.r)
    127 	t.r.when = w
    128 	startTimer(&t.r)
    129 	return active
    130 }
    131 
    132 func sendTime(c interface{}, seq uintptr) {
    133 	// Non-blocking send of time on c.
    134 	// Used in NewTimer, it cannot block anyway (buffer).
    135 	// Used in NewTicker, dropping sends on the floor is
    136 	// the desired behavior when the reader gets behind,
    137 	// because the sends are periodic.
    138 	select {
    139 	case c.(chan Time) <- Now():
    140 	default:
    141 	}
    142 }
    143 
    144 // After waits for the duration to elapse and then sends the current time
    145 // on the returned channel.
    146 // It is equivalent to NewTimer(d).C.
    147 // The underlying Timer is not recovered by the garbage collector
    148 // until the timer fires. If efficiency is a concern, use NewTimer
    149 // instead and call Timer.Stop if the timer is no longer needed.
    150 func After(d Duration) <-chan Time {
    151 	return NewTimer(d).C
    152 }
    153 
    154 // AfterFunc waits for the duration to elapse and then calls f
    155 // in its own goroutine. It returns a Timer that can
    156 // be used to cancel the call using its Stop method.
    157 func AfterFunc(d Duration, f func()) *Timer {
    158 	t := &Timer{
    159 		r: runtimeTimer{
    160 			when: when(d),
    161 			f:    goFunc,
    162 			arg:  f,
    163 		},
    164 	}
    165 	startTimer(&t.r)
    166 	return t
    167 }
    168 
    169 func goFunc(arg interface{}, seq uintptr) {
    170 	go arg.(func())()
    171 }
    172