From e85b99aea9a03dc2d061e9215d6ae8fd76cff2a2 Mon Sep 17 00:00:00 2001 From: marun Date: Thu, 8 Aug 2024 10:19:02 -0700 Subject: [PATCH] Add StoppedTimer helper (#3280) Co-authored-by: Stephen Buttolph --- .../inbound_conn_upgrade_throttler.go | 7 +++--- .../throttling/inbound_resource_throttler.go | 8 +++---- tests/antithesis/avalanchego/main.go | 6 ++--- tests/antithesis/xsvm/main.go | 7 +++--- utils/timer/stopped_timer.go | 24 +++++++++++++++++++ 5 files changed, 35 insertions(+), 17 deletions(-) create mode 100644 utils/timer/stopped_timer.go diff --git a/network/throttling/inbound_conn_upgrade_throttler.go b/network/throttling/inbound_conn_upgrade_throttler.go index 4067d80b2b29..ace53a1fb34b 100644 --- a/network/throttling/inbound_conn_upgrade_throttler.go +++ b/network/throttling/inbound_conn_upgrade_throttler.go @@ -11,6 +11,8 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/avalanchego/utils/set" "github.com/ava-labs/avalanchego/utils/timer/mockable" + + timerpkg "github.com/ava-labs/avalanchego/utils/timer" ) var ( @@ -131,10 +133,7 @@ func (n *inboundConnUpgradeThrottler) ShouldUpgrade(addrPort netip.AddrPort) boo } func (n *inboundConnUpgradeThrottler) Dispatch() { - timer := time.NewTimer(0) - if !timer.Stop() { - <-timer.C - } + timer := timerpkg.StoppedTimer() defer timer.Stop() for { diff --git a/network/throttling/inbound_resource_throttler.go b/network/throttling/inbound_resource_throttler.go index eb915e03232c..967af69a47d2 100644 --- a/network/throttling/inbound_resource_throttler.go +++ b/network/throttling/inbound_resource_throttler.go @@ -15,6 +15,8 @@ import ( "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/snow/networking/tracker" "github.com/ava-labs/avalanchego/utils/timer/mockable" + + timerpkg "github.com/ava-labs/avalanchego/utils/timer" ) const epsilon = time.Millisecond @@ -107,11 +109,7 @@ func NewSystemThrottler( timerPool: sync.Pool{ New: func() interface{} { // Satisfy invariant that timer is stopped and drained. - timer := time.NewTimer(0) - if !timer.Stop() { - <-timer.C - } - return timer + return timerpkg.StoppedTimer() }, }, }, nil diff --git a/tests/antithesis/avalanchego/main.go b/tests/antithesis/avalanchego/main.go index ab297080ffd0..17fc847a1da4 100644 --- a/tests/antithesis/avalanchego/main.go +++ b/tests/antithesis/avalanchego/main.go @@ -33,6 +33,7 @@ import ( "github.com/ava-labs/avalanchego/wallet/subnet/primary" "github.com/ava-labs/avalanchego/wallet/subnet/primary/common" + timerpkg "github.com/ava-labs/avalanchego/utils/timer" xtxs "github.com/ava-labs/avalanchego/vms/avm/txs" ptxs "github.com/ava-labs/avalanchego/vms/platformvm/txs" xbuilder "github.com/ava-labs/avalanchego/wallet/chain/x/builder" @@ -145,10 +146,7 @@ type workload struct { } func (w *workload) run(ctx context.Context) { - timer := time.NewTimer(0) - if !timer.Stop() { - <-timer.C - } + timer := timerpkg.StoppedTimer() tc := tests.NewTestContext() defer tc.Cleanup() diff --git a/tests/antithesis/xsvm/main.go b/tests/antithesis/xsvm/main.go index 31b2e36401c0..6cecf0699d7a 100644 --- a/tests/antithesis/xsvm/main.go +++ b/tests/antithesis/xsvm/main.go @@ -26,6 +26,8 @@ import ( "github.com/ava-labs/avalanchego/vms/example/xsvm/api" "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/issue/status" "github.com/ava-labs/avalanchego/vms/example/xsvm/cmd/issue/transfer" + + timerpkg "github.com/ava-labs/avalanchego/utils/timer" ) const ( @@ -123,10 +125,7 @@ type workload struct { } func (w *workload) run(ctx context.Context) { - timer := time.NewTimer(0) - if !timer.Stop() { - <-timer.C - } + timer := timerpkg.StoppedTimer() tc := tests.NewTestContext() defer tc.Cleanup() diff --git a/utils/timer/stopped_timer.go b/utils/timer/stopped_timer.go new file mode 100644 index 000000000000..1777c830e6e3 --- /dev/null +++ b/utils/timer/stopped_timer.go @@ -0,0 +1,24 @@ +// Copyright (C) 2019-2024, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +package timer + +import "time" + +// StoppedTimer returns a stopped timer so that there is no entry on +// the C channel (and there isn't one scheduled to be added). +// +// This means that after calling Reset there will be no events on the +// channel until the timer fires (at which point there will be exactly +// one event sent to the channel). +// +// It enables re-using the timer across loop iterations without +// needing to have the first loop iteration perform any == nil checks +// to initialize the first invocation. +func StoppedTimer() *time.Timer { + timer := time.NewTimer(0) + if !timer.Stop() { + <-timer.C + } + return timer +}