github.com/searKing/golang/go@v1.2.117/time/sleep.go (about)

     1  // Copyright 2020 The searKing Author. 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  import (
     8  	"time"
     9  )
    10  
    11  // Timer to fix time: Timer.Stop documentation example easily leads to deadlocks
    12  // https://github.com/golang/go/issues/27169
    13  type Timer struct {
    14  	*time.Timer
    15  }
    16  
    17  // Stop prevents the Timer from firing, with the channel drained.
    18  // Stop ensures the channel is empty after a call to Stop.
    19  // Stop == std [Stop + drain]
    20  // It returns true if the call stops the timer, false if the timer has already
    21  // expired or been stopped.
    22  // Stop does not close the channel, to prevent a read from the channel succeeding
    23  // incorrectly.
    24  func (t *Timer) Stop() bool {
    25  	if t.Timer == nil {
    26  		panic("time: Stop called on uninitialized Timer")
    27  	}
    28  
    29  	active := t.Timer.Stop()
    30  	if !active {
    31  		// drain the channel, prevents the Timer from blocking on Send to t.C by sendTime, t.C is reused.
    32  		// The underlying Timer is not recovered by the garbage collector until the timer fires.
    33  		// consume the channel only once for the channel can be triggered only one time at most before Stop is called.
    34  	L:
    35  		for {
    36  			select {
    37  			case _, ok := <-t.Timer.C:
    38  				if !ok {
    39  					break L
    40  				}
    41  			default:
    42  				break L
    43  			}
    44  		}
    45  	}
    46  	return active
    47  }
    48  
    49  // Reset changes the timer to expire after duration d.
    50  // Reset can be invoked anytime, which enhances std time.Reset
    51  // Reset == std [Stop + drain + Reset]
    52  // It returns true if the timer had been active, false if the timer had
    53  // expired or been stopped.
    54  func (t *Timer) Reset(d time.Duration) bool {
    55  	if t.Timer == nil {
    56  		panic("time: Reset called on uninitialized Timer")
    57  	}
    58  	active := t.Stop()
    59  	t.Timer.Reset(d)
    60  	return active
    61  }
    62  
    63  func NewTimer(d time.Duration) *Timer {
    64  	return &Timer{
    65  		Timer: time.NewTimer(d),
    66  	}
    67  }
    68  
    69  func WrapTimer(t *time.Timer) *Timer {
    70  	return &Timer{
    71  		Timer: t,
    72  	}
    73  }
    74  
    75  func After(d time.Duration) <-chan time.Time {
    76  	return NewTimer(d).C
    77  }
    78  
    79  func AfterFunc(d time.Duration, f func()) *Timer {
    80  	t := &Timer{}
    81  	t.Timer = time.AfterFunc(d, func() {
    82  		f()
    83  	})
    84  	return t
    85  }