github.com/telepresenceio/telepresence/v2@v2.20.0-pro.6.0.20240517030216-236ea954e789/pkg/dnet/deadline.go (about) 1 // atomicDeadline is substantially based on pipeDeadline from Go 1.17.1 net/pipe.go. 2 // 3 // Copyright 2021 Datawire. All rights reserved. 4 // 5 // Copyright 2010 The Go Authors. All rights reserved. 6 // Use of this source code is governed by a BSD-style 7 // license that can be found in the LICENSE file. 8 9 package dnet 10 11 import ( 12 "sync" 13 "sync/atomic" 14 "time" 15 ) 16 17 type atomicDeadline struct { 18 // cbMu and timerMu must not be held at the same time. 19 20 // config 21 22 cbMu sync.Locker // must be held to call cb 23 cb func() 24 25 // state 26 27 timerMu sync.Mutex // Guards timer 28 timer *time.Timer 29 30 canceled int32 // atomic 31 } 32 33 func (d *atomicDeadline) set(t time.Time) { 34 d.timerMu.Lock() 35 36 if d.timer != nil { 37 d.timer.Stop() 38 d.timer = nil 39 } 40 41 if t.IsZero() { 42 // Time is zero, then there is no deadline. 43 d.timerMu.Unlock() 44 d.cbMu.Lock() 45 atomic.StoreInt32(&d.canceled, 0) 46 d.cbMu.Unlock() 47 } else if dur := time.Until(t); dur > 0 { 48 // Time is in the future, set up a timer to cancel in the future. 49 d.timer = time.AfterFunc(dur, func() { 50 d.cbMu.Lock() 51 atomic.StoreInt32(&d.canceled, 1) 52 d.cb() 53 d.cbMu.Unlock() 54 }) 55 d.timerMu.Unlock() 56 } else { 57 // time is in the past, so cancel immediately. 58 d.timerMu.Unlock() 59 d.cbMu.Lock() 60 atomic.StoreInt32(&d.canceled, 1) 61 d.cb() 62 d.cbMu.Unlock() 63 } 64 } 65 66 func (d *atomicDeadline) isCanceled() bool { 67 return atomic.LoadInt32(&d.canceled) != 0 68 }