// SPDX-FileCopyrightText: 2023 The Pion community <https://pion.ly>
// SPDX-License-Identifier: MIT

// Package deadline provides deadline timer used to implement // net.Conn compatible connection
package deadline import ( ) type deadlineState uint8 const ( deadlineStopped deadlineState = iota deadlineStarted deadlineExceeded ) var _ context.Context = (*Deadline)(nil) // Deadline signals updatable deadline timer. // Also, it implements context.Context. type Deadline struct { mu sync.RWMutex timer timer done chan struct{} deadline time.Time state deadlineState pending uint8 } // New creates new deadline timer. func () *Deadline { return &Deadline{ done: make(chan struct{}), } } func ( *Deadline) () { .mu.Lock() if .pending--; .pending != 0 || .state != deadlineStarted { .mu.Unlock() return } .state = deadlineExceeded := .done .mu.Unlock() close() } // Set new deadline. Zero value means no deadline. func ( *Deadline) ( time.Time) { .mu.Lock() defer .mu.Unlock() if .state == deadlineStarted && .timer.Stop() { .pending-- } .deadline = .pending++ if .state == deadlineExceeded { .done = make(chan struct{}) } if .IsZero() { .pending-- .state = deadlineStopped return } if := time.Until(); > 0 { .state = deadlineStarted if .timer == nil { .timer = afterFunc(, .timeout) } else { .timer.Reset() } return } .pending-- .state = deadlineExceeded close(.done) } // Done receives deadline signal. func ( *Deadline) () <-chan struct{} { .mu.RLock() defer .mu.RUnlock() return .done } // Err returns context.DeadlineExceeded if the deadline is exceeded. // Otherwise, it returns nil. func ( *Deadline) () error { .mu.RLock() defer .mu.RUnlock() if .state == deadlineExceeded { return context.DeadlineExceeded } return nil } // Deadline returns current deadline. func ( *Deadline) () (time.Time, bool) { .mu.RLock() defer .mu.RUnlock() if .deadline.IsZero() { return .deadline, false } return .deadline, true } // Value returns nil. func ( *Deadline) (interface{}) interface{} { return nil }