Releases: djherbis/stream
Go module support
Return data as soon as possible
stream.Reader supports io.Seeker
Sizable Stream Readers (Range Requests)
Stream Reader supports a new method called Size(). Size returns the size of the entire stream at this moment, and a bool which is true if and only if the stream is closed. If the stream is closed, then the size will be constant from then on, and range requests can be done via an io.SectionReader over the reader like so:
var r stream.Reader
if size, isClosed := r.Size(); isClosed {
sr := io.NewSectionReader(r, 0, size)
http.ServeContent(rw, req, name, modTime, sr)
}
// otherwise just do regular request writing
Concurrent Read/Write calls
tl;dr; Stream's Read/Write calls no longer block each-other, and can safely make progress concurrently.
The last version introduced locks during read/write calls to streams, which synchronized concurrent read/writes, allowing concurrent calls, but not concurrent progress to be made. This was done to insure that sync.Cond was properly broadcasting all reads/writes, so no reader missed a write.
However, this also meant that we were not taking advantage of our concurrent FileSystem under the hood.
I was able to shrink the critical sections for these locks to be very small (it now just keeps track of how much data has been written, and readers use that to see if they've read it all).
Read calls are still sequenced with other reads (but not with Closed, so that you can 'cancel' a blocking read by closing, though concurrent read/close may cause a read to fail.
Writes are sequenced with Write/Close calls so they are safe for concurrent use still.
Concurrent Bug Fixes
Please Update to this Version!
Important Bug Fixes:
- sync.Cond.Wait was not being called atomically. A Broadcast() could occur between RUnlock and Wait() therefore causing the Reader to miss a Write/Close event. If it happened on a Close() it would cause the Reader to block indefinitely. This has been resolved by making the Wait call atomic with RUnlock.
- Stream.Close() now obtains the Write lock such that Broadcast() from a close will only occur while a Reader is Waiting or before a ReadAt call. It's also now safe to call with Write() as the documentation suggested. Though this could lead to a failed Write (on a closed file), but this is always true when closing/writing concurrently.