-
Notifications
You must be signed in to change notification settings - Fork 20
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #58 from libp2p/fix/reuse-deadline-context
don't use contexts for deadlines
- Loading branch information
Showing
3 changed files
with
151 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// Copied from the go standard library. | ||
// | ||
// Copyright 2010 The Go Authors. All rights reserved. | ||
// Use of this source code is governed by a BSD-style | ||
// license that can be found in the LICENSE-BSD file. | ||
|
||
package multiplex | ||
|
||
import ( | ||
"sync" | ||
"time" | ||
) | ||
|
||
// pipeDeadline is an abstraction for handling timeouts. | ||
type pipeDeadline struct { | ||
mu sync.Mutex // Guards timer and cancel | ||
timer *time.Timer | ||
cancel chan struct{} // Must be non-nil | ||
} | ||
|
||
func makePipeDeadline() pipeDeadline { | ||
return pipeDeadline{cancel: make(chan struct{})} | ||
} | ||
|
||
// set sets the point in time when the deadline will time out. | ||
// A timeout event is signaled by closing the channel returned by waiter. | ||
// Once a timeout has occurred, the deadline can be refreshed by specifying a | ||
// t value in the future. | ||
// | ||
// A zero value for t prevents timeout. | ||
func (d *pipeDeadline) set(t time.Time) { | ||
d.mu.Lock() | ||
defer d.mu.Unlock() | ||
|
||
if d.timer != nil && !d.timer.Stop() { | ||
<-d.cancel // Wait for the timer callback to finish and close cancel | ||
} | ||
d.timer = nil | ||
|
||
// Time is zero, then there is no deadline. | ||
closed := isClosedChan(d.cancel) | ||
if t.IsZero() { | ||
if closed { | ||
d.cancel = make(chan struct{}) | ||
} | ||
return | ||
} | ||
|
||
// Time in the future, setup a timer to cancel in the future. | ||
if dur := time.Until(t); dur > 0 { | ||
if closed { | ||
d.cancel = make(chan struct{}) | ||
} | ||
d.timer = time.AfterFunc(dur, func() { | ||
close(d.cancel) | ||
}) | ||
return | ||
} | ||
|
||
// Time in the past, so close immediately. | ||
if !closed { | ||
close(d.cancel) | ||
} | ||
} | ||
|
||
// wait returns a channel that is closed when the deadline is exceeded. | ||
func (d *pipeDeadline) wait() chan struct{} { | ||
d.mu.Lock() | ||
defer d.mu.Unlock() | ||
return d.cancel | ||
} | ||
|
||
func isClosedChan(c <-chan struct{}) bool { | ||
select { | ||
case <-c: | ||
return true | ||
default: | ||
return false | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters