Russ Cox | aa35aee | 2009-02-16 17:07:11 -0800 | [diff] [blame] | 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 | |
Brad Fitzpatrick | 8159b69 | 2013-08-28 11:16:55 -0700 | [diff] [blame] | 7 | // Sleep pauses the current goroutine for at least the duration d. |
| 8 | // A negative or zero duration causes Sleep to return immediately. |
Anthony Martin | 1cb254a | 2011-12-12 16:12:22 -0500 | [diff] [blame] | 9 | func Sleep(d Duration) |
| 10 | |
Jay Weisskopf | 86c976f | 2014-02-24 10:57:46 -0500 | [diff] [blame] | 11 | // runtimeNano returns the current value of the runtime clock in nanoseconds. |
| 12 | func runtimeNano() int64 |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 13 | |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 14 | // Interface to timers implemented in package runtime. |
| 15 | // Must be in sync with ../runtime/runtime.h:/^struct.Timer$ |
| 16 | type runtimeTimer struct { |
Dmitriy Vyukov | 9601aba | 2014-08-25 20:25:22 +0400 | [diff] [blame] | 17 | i int |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 18 | when int64 |
| 19 | period int64 |
Dmitriy Vyukov | 91a670d | 2014-09-04 10:04:04 +0400 | [diff] [blame] | 20 | f func(interface{}, uintptr) // NOTE: must not be closure |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 21 | arg interface{} |
Dmitriy Vyukov | 91a670d | 2014-09-04 10:04:04 +0400 | [diff] [blame] | 22 | seq uintptr |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 23 | } |
| 24 | |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 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 { |
Jay Weisskopf | 86c976f | 2014-02-24 10:57:46 -0500 | [diff] [blame] | 31 | return runtimeNano() |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 32 | } |
Jay Weisskopf | 86c976f | 2014-02-24 10:57:46 -0500 | [diff] [blame] | 33 | t := runtimeNano() + int64(d) |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 34 | if t < 0 { |
| 35 | t = 1<<63 - 1 // math.MaxInt64 |
| 36 | } |
| 37 | return t |
| 38 | } |
| 39 | |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 40 | func startTimer(*runtimeTimer) |
| 41 | func stopTimer(*runtimeTimer) bool |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 42 | |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 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. |
Robert Griesemer | bc89e8c | 2014-10-01 16:44:52 -0700 | [diff] [blame] | 46 | // A Timer must be created with NewTimer or AfterFunc. |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 47 | type Timer struct { |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 48 | C <-chan Time |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 49 | r runtimeTimer |
| 50 | } |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 51 | |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 52 | // Stop prevents the Timer from firing. |
| 53 | // It returns true if the call stops the timer, false if the timer has already |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 54 | // expired or been stopped. |
Shenghou Ma | 48b739c | 2012-11-08 23:25:48 +0800 | [diff] [blame] | 55 | // Stop does not close the channel, to prevent a read from the channel succeeding |
| 56 | // incorrectly. |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 57 | func (t *Timer) Stop() bool { |
Brad Fitzpatrick | ab4af52 | 2014-10-21 13:26:40 +0200 | [diff] [blame] | 58 | if t.r.f == nil { |
| 59 | panic("time: Stop called on uninitialized Timer") |
| 60 | } |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 61 | return stopTimer(&t.r) |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 62 | } |
| 63 | |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 64 | // NewTimer creates a new Timer that will send |
Sameer Ajmani | 1379d90 | 2012-01-07 20:53:53 -0500 | [diff] [blame] | 65 | // the current time on its channel after at least duration d. |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 66 | func NewTimer(d Duration) *Timer { |
| 67 | c := make(chan Time, 1) |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 68 | t := &Timer{ |
| 69 | C: c, |
| 70 | r: runtimeTimer{ |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 71 | when: when(d), |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 72 | f: sendTime, |
| 73 | arg: c, |
| 74 | }, |
| 75 | } |
| 76 | startTimer(&t.r) |
| 77 | return t |
| 78 | } |
| 79 | |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 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 { |
Brad Fitzpatrick | ab4af52 | 2014-10-21 13:26:40 +0200 | [diff] [blame] | 84 | if t.r.f == nil { |
| 85 | panic("time: Reset called on uninitialized Timer") |
| 86 | } |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 87 | w := when(d) |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 88 | active := stopTimer(&t.r) |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 89 | t.r.when = w |
Volker Dobler | 44ff17e | 2013-01-17 14:41:53 +1100 | [diff] [blame] | 90 | startTimer(&t.r) |
| 91 | return active |
| 92 | } |
| 93 | |
Dmitriy Vyukov | 91a670d | 2014-09-04 10:04:04 +0400 | [diff] [blame] | 94 | func sendTime(c interface{}, seq uintptr) { |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 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 { |
Jay Weisskopf | 86c976f | 2014-02-24 10:57:46 -0500 | [diff] [blame] | 101 | case c.(chan Time) <- Now(): |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 102 | default: |
| 103 | } |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 104 | } |
| 105 | |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 106 | // After waits for the duration to elapse and then sends the current time |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 107 | // on the returned channel. |
Sameer Ajmani | 1379d90 | 2012-01-07 20:53:53 -0500 | [diff] [blame] | 108 | // It is equivalent to NewTimer(d).C. |
Russ Cox | efe3d35 | 2011-11-30 11:59:44 -0500 | [diff] [blame] | 109 | func After(d Duration) <-chan Time { |
| 110 | return NewTimer(d).C |
Roger Peppe | 212e074 | 2011-01-10 11:51:38 -0800 | [diff] [blame] | 111 | } |
| 112 | |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 113 | // AfterFunc waits for the duration to elapse and then calls f |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 114 | // in its own goroutine. It returns a Timer that can |
| 115 | // be used to cancel the call using its Stop method. |
David Symonds | 2949f3b | 2011-12-08 15:42:44 +1100 | [diff] [blame] | 116 | func AfterFunc(d Duration, f func()) *Timer { |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 117 | t := &Timer{ |
| 118 | r: runtimeTimer{ |
Andrew Gerrand | 89cf67e | 2013-02-26 09:23:58 +1100 | [diff] [blame] | 119 | when: when(d), |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 120 | f: goFunc, |
| 121 | arg: f, |
| 122 | }, |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 123 | } |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 124 | startTimer(&t.r) |
| 125 | return t |
Roger Peppe | 2ae953b | 2011-01-25 12:25:48 -0800 | [diff] [blame] | 126 | } |
| 127 | |
Dmitriy Vyukov | 91a670d | 2014-09-04 10:04:04 +0400 | [diff] [blame] | 128 | func goFunc(arg interface{}, seq uintptr) { |
Russ Cox | 3b86026 | 2011-11-09 15:17:05 -0500 | [diff] [blame] | 129 | go arg.(func())() |
Roger Peppe | e2d1595 | 2010-12-06 14:19:30 -0500 | [diff] [blame] | 130 | } |