Source file src/time/sleep.go

     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  // Interface to timers implemented in package runtime.
    12  // Must be in sync with ../runtime/time.go:/^type timer
    13  type runtimeTimer struct {
    14  	pp       uintptr
    15  	when     int64
    16  	period   int64
    17  	f        func(any, uintptr) // NOTE: must not be closure
    18  	arg      any
    19  	seq      uintptr
    20  	nextwhen int64
    21  	status   uint32
    22  }
    23  
    24  // when is a helper function for setting the 'when' field of a runtimeTimer.
    25  // It returns what the time will be, in nanoseconds, Duration d in the future.
    26  // If d is negative, it is ignored. If the returned value would be less than
    27  // zero because of an overflow, MaxInt64 is returned.
    28  func when(d Duration) int64 {
    29  	if d <= 0 {
    30  		return runtimeNano()
    31  	}
    32  	t := runtimeNano() + int64(d)
    33  	if t < 0 {
    34  		// N.B. runtimeNano() and d are always positive, so addition
    35  		// (including overflow) will never result in t == 0.
    36  		t = 1<<63 - 1 // math.MaxInt64
    37  	}
    38  	return t
    39  }
    40  
    41  func startTimer(*runtimeTimer)
    42  func stopTimer(*runtimeTimer) bool
    43  func resetTimer(*runtimeTimer, int64) bool
    44  func modTimer(t *runtimeTimer, when, period int64, f func(any, uintptr), arg any, seq uintptr)
    45  
    46  // The Timer type represents a single event.
    47  // When the Timer expires, the current time will be sent on C,
    48  // unless the Timer was created by AfterFunc.
    49  // A Timer must be created with NewTimer or AfterFunc.
    50  type Timer struct {
    51  	C <-chan Time
    52  	r runtimeTimer
    53  }
    54  
    55  // Stop prevents the Timer from firing.
    56  // It returns true if the call stops the timer, false if the timer has already
    57  // expired or been stopped.
    58  // Stop does not close the channel, to prevent a read from the channel succeeding
    59  // incorrectly.
    60  //
    61  // To ensure the channel is empty after a call to Stop, check the
    62  // return value and drain the channel.
    63  // For example, assuming the program has not received from t.C already:
    64  //
    65  // 	if !t.Stop() {
    66  // 		<-t.C
    67  // 	}
    68  //
    69  // This cannot be done concurrent to other receives from the Timer's
    70  // channel or other calls to the Timer's Stop method.
    71  //
    72  // For a timer created with AfterFunc(d, f), if t.Stop returns false, then the timer
    73  // has already expired and the function f has been started in its own goroutine;
    74  // Stop does not wait for f to complete before returning.
    75  // If the caller needs to know whether f is completed, it must coordinate
    76  // with f explicitly.
    77  func (t *Timer) Stop() bool {
    78  	if t.r.f == nil {
    79  		panic("time: Stop called on uninitialized Timer")
    80  	}
    81  	return stopTimer(&t.r)
    82  }
    83  
    84  // NewTimer creates a new Timer that will send
    85  // the current time on its channel after at least duration d.
    86  func NewTimer(d Duration) *Timer {
    87  	c := make(chan Time, 1)
    88  	t := &Timer{
    89  		C: c,
    90  		r: runtimeTimer{
    91  			when: when(d),
    92  			f:    sendTime,
    93  			arg:  c,
    94  		},
    95  	}
    96  	startTimer(&t.r)
    97  	return t
    98  }
    99  
   100  // Reset changes the timer to expire after duration d.
   101  // It returns true if the timer had been active, false if the timer had
   102  // expired or been stopped.
   103  //
   104  // For a Timer created with NewTimer, Reset should be invoked only on
   105  // stopped or expired timers with drained channels.
   106  //
   107  // If a program has already received a value from t.C, the timer is known
   108  // to have expired and the channel drained, so t.Reset can be used directly.
   109  // If a program has not yet received a value from t.C, however,
   110  // the timer must be stopped and—if Stop reports that the timer expired
   111  // before being stopped—the channel explicitly drained:
   112  //
   113  // 	if !t.Stop() {
   114  // 		<-t.C
   115  // 	}
   116  // 	t.Reset(d)
   117  //
   118  // This should not be done concurrent to other receives from the Timer's
   119  // channel.
   120  //
   121  // Note that it is not possible to use Reset's return value correctly, as there
   122  // is a race condition between draining the channel and the new timer expiring.
   123  // Reset should always be invoked on stopped or expired channels, as described above.
   124  // The return value exists to preserve compatibility with existing programs.
   125  //
   126  // For a Timer created with AfterFunc(d, f), Reset either reschedules
   127  // when f will run, in which case Reset returns true, or schedules f
   128  // to run again, in which case it returns false.
   129  // When Reset returns false, Reset neither waits for the prior f to
   130  // complete before returning nor does it guarantee that the subsequent
   131  // goroutine running f does not run concurrently with the prior
   132  // one. If the caller needs to know whether the prior execution of
   133  // f is completed, it must coordinate with f explicitly.
   134  func (t *Timer) Reset(d Duration) bool {
   135  	if t.r.f == nil {
   136  		panic("time: Reset called on uninitialized Timer")
   137  	}
   138  	w := when(d)
   139  	return resetTimer(&t.r, w)
   140  }
   141  
   142  // sendTime does a non-blocking send of the current time on c.
   143  func sendTime(c any, seq uintptr) {
   144  	select {
   145  	case c.(chan Time) <- Now():
   146  	default:
   147  	}
   148  }
   149  
   150  // After waits for the duration to elapse and then sends the current time
   151  // on the returned channel.
   152  // It is equivalent to NewTimer(d).C.
   153  // The underlying Timer is not recovered by the garbage collector
   154  // until the timer fires. If efficiency is a concern, use NewTimer
   155  // instead and call Timer.Stop if the timer is no longer needed.
   156  func After(d Duration) <-chan Time {
   157  	return NewTimer(d).C
   158  }
   159  
   160  // AfterFunc waits for the duration to elapse and then calls f
   161  // in its own goroutine. It returns a Timer that can
   162  // be used to cancel the call using its Stop method.
   163  func AfterFunc(d Duration, f func()) *Timer {
   164  	t := &Timer{
   165  		r: runtimeTimer{
   166  			when: when(d),
   167  			f:    goFunc,
   168  			arg:  f,
   169  		},
   170  	}
   171  	startTimer(&t.r)
   172  	return t
   173  }
   174  
   175  func goFunc(arg any, seq uintptr) {
   176  	go arg.(func())()
   177  }
   178  

View as plain text