status-go/vendor/github.com/pion/transport/v2/deadline/deadline.go

125 lines
2.2 KiB
Go
Raw Normal View History

2024-05-15 23:15:00 +00:00
// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT
2022-03-10 09:44:48 +00:00
// Package deadline provides deadline timer used to implement
// net.Conn compatible connection
package deadline
import (
"context"
"sync"
"time"
)
2024-06-05 20:10:03 +00:00
type deadlineState uint8
const (
deadlineStopped deadlineState = iota
deadlineStarted
deadlineExceeded
)
var _ context.Context = (*Deadline)(nil)
2022-03-10 09:44:48 +00:00
// Deadline signals updatable deadline timer.
// Also, it implements context.Context.
type Deadline struct {
mu sync.RWMutex
2024-06-05 20:10:03 +00:00
timer timer
done chan struct{}
deadline time.Time
state deadlineState
pending uint8
2022-03-10 09:44:48 +00:00
}
// New creates new deadline timer.
func New() *Deadline {
2024-06-05 20:10:03 +00:00
return &Deadline{
done: make(chan struct{}),
2022-03-10 09:44:48 +00:00
}
2024-06-05 20:10:03 +00:00
}
func (d *Deadline) timeout() {
d.mu.Lock()
if d.pending--; d.pending != 0 || d.state != deadlineStarted {
d.mu.Unlock()
return
}
d.state = deadlineExceeded
done := d.done
d.mu.Unlock()
close(done)
2022-03-10 09:44:48 +00:00
}
// Set new deadline. Zero value means no deadline.
func (d *Deadline) Set(t time.Time) {
d.mu.Lock()
defer d.mu.Unlock()
2024-06-05 20:10:03 +00:00
if d.state == deadlineStarted && d.timer.Stop() {
d.pending--
}
2022-03-10 09:44:48 +00:00
2024-06-05 20:10:03 +00:00
d.deadline = t
d.pending++
2022-03-10 09:44:48 +00:00
2024-06-05 20:10:03 +00:00
if d.state == deadlineExceeded {
d.done = make(chan struct{})
2022-03-10 09:44:48 +00:00
}
if t.IsZero() {
2024-06-05 20:10:03 +00:00
d.pending--
d.state = deadlineStopped
2022-03-10 09:44:48 +00:00
return
}
if dur := time.Until(t); dur > 0 {
2024-06-05 20:10:03 +00:00
d.state = deadlineStarted
if d.timer == nil {
d.timer = afterFunc(dur, d.timeout)
} else {
d.timer.Reset(dur)
}
2022-03-10 09:44:48 +00:00
return
}
2024-06-05 20:10:03 +00:00
d.pending--
d.state = deadlineExceeded
close(d.done)
2022-03-10 09:44:48 +00:00
}
// Done receives deadline signal.
func (d *Deadline) Done() <-chan struct{} {
d.mu.RLock()
defer d.mu.RUnlock()
2024-06-05 20:10:03 +00:00
return d.done
2022-03-10 09:44:48 +00:00
}
// 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()
2024-06-05 20:10:03 +00:00
if d.state == deadlineExceeded {
2022-03-10 09:44:48 +00:00
return context.DeadlineExceeded
}
2024-06-05 20:10:03 +00:00
return nil
2022-03-10 09:44:48 +00:00
}
// 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
}