github.com/webmafia/fast@v0.10.0/clock.go (about)

     1  package fast
     2  
     3  import (
     4  	"context"
     5  	"sync/atomic"
     6  	"time"
     7  )
     8  
     9  type Clock struct {
    10  	ts int64
    11  }
    12  
    13  func NewClock(ctx context.Context) *Clock {
    14  	c := &Clock{
    15  		ts: time.Now().Unix(),
    16  	}
    17  
    18  	go c.tick(ctx)
    19  
    20  	return c
    21  }
    22  
    23  //go:inline
    24  func (c *Clock) Now() time.Time {
    25  	return time.Unix(c.Unix(), 0)
    26  }
    27  
    28  //go:inline
    29  func (c *Clock) Unix() int64 {
    30  	return atomic.LoadInt64(&c.ts)
    31  }
    32  
    33  func (c *Clock) tick(ctx context.Context) {
    34  	ticker := time.NewTicker(time.Second)
    35  	now := time.Now()
    36  
    37  	// Wait to the next second
    38  	nextSec := now.Truncate(time.Second).Add(time.Second)
    39  	delay := nextSec.Sub(now)
    40  
    41  	if delay > 0 {
    42  		ticker.Reset(delay)
    43  		<-ticker.C
    44  		ticker.Reset(time.Second)
    45  	}
    46  
    47  	for {
    48  		select {
    49  		case <-ctx.Done():
    50  			return
    51  		case ts := <-ticker.C:
    52  			atomic.StoreInt64(&c.ts, ts.Unix())
    53  		}
    54  	}
    55  }