github.com/GeniusesGroup/libgo@v0.0.0-20220929090155-5ff932cb408e/timer/timer-sync.go (about)

     1  /* For license and copyright information please see the LEGAL file in the code repository */
     2  
     3  package timer
     4  
     5  import (
     6  	"github.com/GeniusesGroup/libgo/protocol"
     7  )
     8  
     9  // After waits for the duration to elapse and then sends signal on the returned channel.
    10  // The underlying Timer is not recovered by the garbage collector
    11  // until the timer fires. If efficiency is a concern, copy the body
    12  // instead and call timer.Stop() if the timer is no longer needed.
    13  // It will **panic** if it can't start the timer due to any situation like not enough memory, ...
    14  func After(d protocol.Duration) <-chan struct{} {
    15  	var timer Sync
    16  	timer.Init()
    17  	var err = timer.Start(d)
    18  	if err != nil {
    19  		panic(err)
    20  	}
    21  	return timer.Signal()
    22  }
    23  
    24  // NewAsync waits for the duration to elapse and then calls callback.
    25  // If callback need blocking operation it must do its logic in new thread(goroutine).
    26  // It returns a SyncTimer that can be used to cancel the call using its Stop method.
    27  func NewSync(d protocol.Duration) (t *Sync, err protocol.Error) {
    28  	var timer Sync
    29  	timer.Init()
    30  	err = timer.Start(d)
    31  	t = &timer
    32  	return
    33  }
    34  
    35  // Sync Timer must be created with Init, After or AfterFunc.
    36  type Sync struct {
    37  	Async
    38  	signal chan struct{}
    39  }
    40  
    41  func (t *Sync) Reinit() { t.Stop(); close(t.signal); t.Async.Reinit() }
    42  func (t *Sync) Deinit() { t.Stop(); close(t.signal) }
    43  
    44  //libgo:impl protocol.Timer
    45  func (t *Sync) Init() {
    46  	// Give the channel a 1-element buffer.
    47  	// If the client falls behind while reading, we drop ticks
    48  	// on the floor until the client catches up.
    49  	t.signal = make(chan struct{}, 1)
    50  	t.Async.Init(t)
    51  }
    52  func (t *Sync) Signal() <-chan struct{}                           { return t.signal }
    53  func (t *Sync) Start(d protocol.Duration) (err protocol.Error)    { return t.Async.Start(d) }
    54  func (t *Sync) Stop() (alreadyStopped bool)                       { return t.Async.Stop() }
    55  func (t *Sync) Reset(d protocol.Duration) (alreadyActivated bool) { return t.Modify(d) }
    56  
    57  // TimerHandler or NotifyChannel does a non-blocking send the signal on t.signal
    58  func (t *Sync) TimerHandler() {
    59  	select {
    60  	case t.signal <- struct{}{}:
    61  	default:
    62  	}
    63  }