- From: Mattias Buelens <notifications@github.com>
- Date: Thu, 10 Feb 2022 04:22:59 -0800
- To: whatwg/streams <streams@noreply.github.com>
- Cc: Subscribed <subscribed@noreply.github.com>
- Message-ID: <whatwg/streams/issues/1217/1034859874@github.com>
> An alternative or perhaps a companion to BYOB readers is the concept of a "two-phase" read where the `UnderlyingSource` enqueues a chunk but can get a later signal that the buffer holding that chunk is no longer in use and so can be reused for another chunk. It sounds like you want an API where the *underlying source* is in control of how its buffer is re-used for repeated `enqueue()` calls, rather than relying on the reader to re-use the same buffer for repeated `read(view)` calls? Then you'd need a quite different reader API too. Right now, `read(view)` returns a view, and the consumer can do whatever it wants with that view for however long it wants. Instead, we'd need an API to *restrict* how long the consumer can use the view. Some ideas: * Add a `reader.reclaim(buffer)` method. This might be quite error-prone though, or even confusing if you're doing multiple parallel reads across multiple buffers. * Add an async callback argment to `reader.read()`, which is called with the `{ done, value }` tuple. That value will only remain valid for the duration of the async callback, so the stream can automatically reclaim its buffer when the callback completes. (This is inspired by [Web Locks `request()`](https://developer.mozilla.org/en-US/docs/Web/API/LockManager/request).) Another pain point is that the consumer might want to *re-transfer* the buffer a couple of times before returning ownership of the buffer to the stream. So it's not good enough to look at the *original* value of `value.buffer`, we'd need a way to reclaim ownership of the *final* (possibly re-transferred) buffer. > This could be useful, for example, when the data source being wrapped by the `UnderlyingSource` provides a BYOB-style API and the buffers passed as chunks to `enqueue()` could eventually be reused once they have been returned to the source. Not entirely sure why you'd need this, since this already works today: ```javascript let stream = new ReadableStream({ type: 'bytes', /* ... */ }); let reader = stream.getReader({ mode: 'byob' }); let wrappedStream = new ReadableStream({ type: 'bytes', autoAllocateChunkSize: 1024, // ensure byobRequest exists, even when using a default reader async pull(controller) { const { done, value } = await reader.read(controller.byobRequest.view); if (done) { controller.close(); } controller.byobRequest.respondWithNewView(value); }, async cancel(reason) { await reader.cancel(reason); } }); ``` But yes, that requires the *consumer* to re-use the buffer. The underlying source has no say in this. > It could also be useful for sources implemented by the platform which read data from shared memory Correct me if I'm wrong, but I *think* this requires `SharedArrayBuffer`s? I don't think it's safe to construct a regular `ArrayBuffer` on top of a shared memory region. That makes things quite difficult. We rely on transferring `ArrayBuffer`s to pass ownership around, but `SharedArrayBuffer`s are not transferable. We'd have to revisit a lot of our assumptions if we cannot transfer buffers within the stream. Also, I'm not sure how a reader API would *safely* use chunks backed by shared array buffers. 😕 -- Reply to this email directly or view it on GitHub: https://github.com/whatwg/streams/issues/1217#issuecomment-1034859874 You are receiving this because you are subscribed to this thread. Message ID: <whatwg/streams/issues/1217/1034859874@github.com>
Received on Thursday, 10 February 2022 12:23:12 UTC