From e84d912c8707f844d1b9441a592fad55378bd61d Mon Sep 17 00:00:00 2001 From: sukun Date: Mon, 12 Jun 2023 14:01:52 +0530 Subject: [PATCH] core: document why InstantTimer is required originally explained by @marcopolo here: https://github.com/libp2p/go-libp2p/pull/2260#discussion_r1201284744 --- core/test/mockclock.go | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/core/test/mockclock.go b/core/test/mockclock.go index 1ed7250332..4916465586 100644 --- a/core/test/mockclock.go +++ b/core/test/mockclock.go @@ -50,6 +50,14 @@ func NewMockClock() *MockClock { return &MockClock{now: time.Unix(0, 0), advanceBySem: make(chan struct{}, 1)} } +// InstantTimer implements a timer that triggers at a fixed instant in time as opposed to after a +// fixed duration from the moment of creation/reset. +// +// In test environments, when using a Timer which fires after a duration, there is a race between +// the goroutine moving time forward using `clock.Advanceby` and the goroutine resetting the +// timer by doing `timer.Reset(desiredInstant.Sub(time.Now()))`. The value of +// `desiredInstance.sub(time.Now())` is different depending on whether `clock.AdvanceBy` finishes +// before or after the timer reset. func (c *MockClock) InstantTimer(when time.Time) *mockInstantTimer { c.mu.Lock() defer c.mu.Unlock()