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/runtime.h:/^struct.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 func (t *Timer) Stop() bool {
     58 	if t.r.f == nil {
     59 		panic("time: Stop called on uninitialized Timer")
     60 	}
     61 	return stopTimer(&t.r)
     62 }
     63 
     64 // NewTimer creates a new Timer that will send
     65 // the current time on its channel after at least duration d.
     66 func NewTimer(d Duration) *Timer {
     67 	c := make(chan Time, 1)
     68 	t := &Timer{
     69 		C: c,
     70 		r: runtimeTimer{
     71 			when: when(d),
     72 			f:    sendTime,
     73 			arg:  c,
     74 		},
     75 	}
     76 	startTimer(&t.r)
     77 	return t
     78 }
     79 
     80 // Reset changes the timer to expire after duration d.
     81 // It returns true if the timer had been active, false if the timer had
     82 // expired or been stopped.
     83 func (t *Timer) Reset(d Duration) bool {
     84 	if t.r.f == nil {
     85 		panic("time: Reset called on uninitialized Timer")
     86 	}
     87 	w := when(d)
     88 	active := stopTimer(&t.r)
     89 	t.r.when = w
     90 	startTimer(&t.r)
     91 	return active
     92 }
     93 
     94 func sendTime(c interface{}, seq uintptr) {
     95 	// Non-blocking send of time on c.
     96 	// Used in NewTimer, it cannot block anyway (buffer).
     97 	// Used in NewTicker, dropping sends on the floor is
     98 	// the desired behavior when the reader gets behind,
     99 	// because the sends are periodic.
    100 	select {
    101 	case c.(chan Time) <- Now():
    102 	default:
    103 	}
    104 }
    105 
    106 // After waits for the duration to elapse and then sends the current time
    107 // on the returned channel.
    108 // It is equivalent to NewTimer(d).C.
    109 func After(d Duration) <-chan Time {
    110 	return NewTimer(d).C
    111 }
    112 
    113 // AfterFunc waits for the duration to elapse and then calls f
    114 // in its own goroutine. It returns a Timer that can
    115 // be used to cancel the call using its Stop method.
    116 func AfterFunc(d Duration, f func()) *Timer {
    117 	t := &Timer{
    118 		r: runtimeTimer{
    119 			when: when(d),
    120 			f:    goFunc,
    121 			arg:  f,
    122 		},
    123 	}
    124 	startTimer(&t.r)
    125 	return t
    126 }
    127 
    128 func goFunc(arg interface{}, seq uintptr) {
    129 	go arg.(func())()
    130 }
    131