github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/session/mbtime/mbtime.go (about)

     1  /*
     2   * Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
     3   *
     4   * This program is free software: you can redistribute it and/or modify
     5   * it under the terms of the GNU General Public License as published by
     6   * the Free Software Foundation, either version 3 of the License, or
     7   * (at your option) any later version.
     8   *
     9   * This program is distributed in the hope that it will be useful,
    10   * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12   * GNU General Public License for more details.
    13   *
    14   * You should have received a copy of the GNU General Public License
    15   * along with this program.  If not, see <http://www.gnu.org/licenses/>.
    16   */
    17  
    18  package mbtime
    19  
    20  import (
    21  	"syscall"
    22  	"time"
    23  
    24  	// Needed for go:linkname
    25  	_ "unsafe"
    26  
    27  	"github.com/rs/zerolog/log"
    28  )
    29  
    30  // Time represents structure for calculating elapsed duration between time interval.
    31  // It uses different syscalls depending on platform expect for Windows it uses std
    32  // library time since it already includes boottime.
    33  type Time struct {
    34  	// ns represents suspend-aware monotonic clock time in nanoseconds.
    35  	ns time.Duration
    36  }
    37  
    38  // Now returns current suspend-aware monotonic time.
    39  func Now() Time {
    40  	ts, err := nanotime()
    41  	if err != nil {
    42  		log.Error().Err(err).Msgf("Using fallback time")
    43  		return Time{ns: time.Duration(nanotimeFallback())}
    44  	}
    45  	return Time{ns: time.Duration(ts)}
    46  }
    47  
    48  // New creates new suspend-aware monotonic time from given initial values.
    49  // This is mostly useful for unit tests.
    50  func New(sec int64, nsec int64) Time {
    51  	return Time{ns: time.Duration(sec*1e9 + nsec)}
    52  }
    53  
    54  // Nano returns current duration in nanoseconds.
    55  func (t Time) Nano() time.Duration {
    56  	return t.ns
    57  }
    58  
    59  const (
    60  	minDuration time.Duration = -1 << 63
    61  	maxDuration time.Duration = 1<<63 - 1
    62  )
    63  
    64  // Sub returns the duration t-u.
    65  func (t Time) Sub(u Time) time.Duration {
    66  	d := t.ns - u.ns
    67  	if d < 0 && t.ns > u.ns {
    68  		return maxDuration // t - u is positive out of range
    69  	}
    70  	if d > 0 && t.ns < u.ns {
    71  		return minDuration // t - u is negative out of range
    72  	}
    73  	return d
    74  }
    75  
    76  // String returns time formatted time string.
    77  func (t Time) String() string {
    78  	return t.ns.String()
    79  }
    80  
    81  // Since returns the time elapsed since t.
    82  // It is shorthand for time.Now().Sub(t).
    83  func Since(u Time) time.Duration {
    84  	return Now().ns - u.ns
    85  }
    86  
    87  func tempSyscallErr(err error) bool {
    88  	errno, ok := err.(syscall.Errno)
    89  	if !ok {
    90  		return false
    91  	}
    92  	return errno.Temporary()
    93  }
    94  
    95  //go:noescape
    96  //go:linkname nanotimeFallback runtime.nanotime
    97  func nanotimeFallback() int64