go.crypto/ssh: make {client,server}Chan use common window management

R=agl, gustav.paul, kardianos
CC=golang-dev
https://golang.org/cl/6208043
This commit is contained in:
Dave Cheney
2012-05-11 05:56:44 +10:00
parent 523290a72d
commit 8a2e7c966a
4 changed files with 76 additions and 82 deletions
+47
View File
@@ -285,3 +285,50 @@ func appendU32(buf []byte, n uint32) []byte {
func appendInt(buf []byte, n int) []byte {
return appendU32(buf, uint32(n))
}
// newCond is a helper to hide the fact that there is no usable zero
// value for sync.Cond.
func newCond() *sync.Cond { return sync.NewCond(new(sync.Mutex)) }
// window represents the buffer available to clients
// wishing to write to a channel.
type window struct {
*sync.Cond
win uint32 // RFC 4254 5.2 says the window size can grow to 2^32-1
}
// add adds win to the amount of window available
// for consumers.
func (w *window) add(win uint32) bool {
if win == 0 {
return false
}
w.L.Lock()
if w.win+win < win {
w.L.Unlock()
return false
}
w.win += win
// It is unusual that multiple goroutines would be attempting to reserve
// window space, but not guaranteed. Use broadcast to notify all waiters
// that additional window is available.
w.Broadcast()
w.L.Unlock()
return true
}
// reserve reserves win from the available window capacity.
// If no capacity remains, reserve will block. reserve may
// return less than requested.
func (w *window) reserve(win uint32) uint32 {
w.L.Lock()
for w.win == 0 {
w.Wait()
}
if w.win < win {
win = w.win
}
w.win -= win
w.L.Unlock()
return win
}