// 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 yamux

import (
	
	
)

// 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 ( *pipeDeadline) ( time.Time) {
	.mu.Lock()
	defer .mu.Unlock()

	if .timer != nil && !.timer.Stop() {
		<-.cancel // Wait for the timer callback to finish and close cancel
	}
	.timer = nil

	// Time is zero, then there is no deadline.
	 := isClosedChan(.cancel)
	if .IsZero() {
		if  {
			.cancel = make(chan struct{})
		}
		return
	}

	// Time in the future, setup a timer to cancel in the future.
	if  := time.Until();  > 0 {
		if  {
			.cancel = make(chan struct{})
		}
		.timer = time.AfterFunc(, func() {
			close(.cancel)
		})
		return
	}

	// Time in the past, so close immediately.
	if ! {
		close(.cancel)
	}
}

// wait returns a channel that is closed when the deadline is exceeded.
func ( *pipeDeadline) () chan struct{} {
	.mu.Lock()
	defer .mu.Unlock()
	return .cancel
}

func isClosedChan( <-chan struct{}) bool {
	select {
	case <-:
		return true
	default:
		return false
	}
}