summaryrefslogtreecommitdiff
path: root/vendor/github.com/pion/transport/deadline/deadline.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/pion/transport/deadline/deadline.go')
-rw-r--r--vendor/github.com/pion/transport/deadline/deadline.go110
1 files changed, 110 insertions, 0 deletions
diff --git a/vendor/github.com/pion/transport/deadline/deadline.go b/vendor/github.com/pion/transport/deadline/deadline.go
new file mode 100644
index 0000000..6f97386
--- /dev/null
+++ b/vendor/github.com/pion/transport/deadline/deadline.go
@@ -0,0 +1,110 @@
+// Package deadline provides deadline timer used to implement
+// net.Conn compatible connection
+package deadline
+
+import (
+ "context"
+ "sync"
+ "time"
+)
+
+// Deadline signals updatable deadline timer.
+// Also, it implements context.Context.
+type Deadline struct {
+ exceeded chan struct{}
+ stop chan struct{}
+ stopped chan bool
+ deadline time.Time
+ mu sync.RWMutex
+}
+
+// New creates new deadline timer.
+func New() *Deadline {
+ d := &Deadline{
+ exceeded: make(chan struct{}),
+ stop: make(chan struct{}),
+ stopped: make(chan bool, 1),
+ }
+ d.stopped <- true
+ return d
+}
+
+// Set new deadline. Zero value means no deadline.
+func (d *Deadline) Set(t time.Time) {
+ d.mu.Lock()
+ defer d.mu.Unlock()
+
+ d.deadline = t
+
+ close(d.stop)
+
+ select {
+ case <-d.exceeded:
+ d.exceeded = make(chan struct{})
+ default:
+ stopped := <-d.stopped
+ if !stopped {
+ d.exceeded = make(chan struct{})
+ }
+ }
+ d.stop = make(chan struct{})
+ d.stopped = make(chan bool, 1)
+
+ if t.IsZero() {
+ d.stopped <- true
+ return
+ }
+
+ if dur := time.Until(t); dur > 0 {
+ exceeded := d.exceeded
+ stopped := d.stopped
+ go func() {
+ select {
+ case <-time.After(dur):
+ close(exceeded)
+ stopped <- false
+ case <-d.stop:
+ stopped <- true
+ }
+ }()
+ return
+ }
+
+ close(d.exceeded)
+ d.stopped <- false
+}
+
+// Done receives deadline signal.
+func (d *Deadline) Done() <-chan struct{} {
+ d.mu.RLock()
+ defer d.mu.RUnlock()
+ return d.exceeded
+}
+
+// Err returns context.DeadlineExceeded if the deadline is exceeded.
+// Otherwise, it returns nil.
+func (d *Deadline) Err() error {
+ d.mu.RLock()
+ defer d.mu.RUnlock()
+ select {
+ case <-d.exceeded:
+ return context.DeadlineExceeded
+ default:
+ return nil
+ }
+}
+
+// Deadline returns current deadline.
+func (d *Deadline) Deadline() (time.Time, bool) {
+ d.mu.RLock()
+ defer d.mu.RUnlock()
+ if d.deadline.IsZero() {
+ return d.deadline, false
+ }
+ return d.deadline, true
+}
+
+// Value returns nil.
+func (d *Deadline) Value(interface{}) interface{} {
+ return nil
+}