From 5d6ec53d1da0ac8d44105cd1c6b3bf8ebfac480e Mon Sep 17 00:00:00 2001 From: Tim Gross Date: Tue, 1 Oct 2024 08:56:49 -0400 Subject: [PATCH] docs: clarify the semantics of concurrent `Read` calls Concurrent operations on the stream are "safe" inasmuch as they don't cause a data race. That is, calling close concurrently with a read won't panic, you can write and read concurrently, and reading from two different goroutines shouldn't result in short reads. But there's no intended guarantee that the reads are semantically meaningful if you're reading concurrently. Fixes: https://github.com/hashicorp/yamux/issues/128 --- stream.go | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/stream.go b/stream.go index 31168d9..df70ddf 100644 --- a/stream.go +++ b/stream.go @@ -91,7 +91,9 @@ func (s *Stream) StreamID() uint32 { return s.id } -// Read is used to read from the stream +// Read is used to read from the stream. It is safe to call Write, Read, and/or +// Close concurrently but Stream provides no guarantees that concurrent Reads +// will receive data in response to Writes made from the same goroutine. func (s *Stream) Read(b []byte) (n int, err error) { defer asyncNotify(s.recvNotifyCh) START: @@ -158,7 +160,9 @@ WAIT: goto START } -// Write is used to write to the stream +// Write is used to write to the stream. It is safe to call Write, Read, and/or +// Close concurrently but Stream provides no guarantees that concurrent Reads +// will receive data in response to Writes made from the same goroutine. func (s *Stream) Write(b []byte) (n int, err error) { s.sendLock.Lock() defer s.sendLock.Unlock() @@ -320,7 +324,8 @@ func (s *Stream) sendClose() error { return nil } -// Close is used to close the stream +// Close is used to close the stream. It is safe to call Write, Read, and/or +// Close concurrently. func (s *Stream) Close() error { closeStream := false s.stateLock.Lock()