Hi,
On Sat, Feb 13, 2021 at 5:33 PM Adrien Destugues
<pulkomandy@xxxxxxxxxxxxx> wrote:
So that answers the first part of my concern, but I still wonder
whether the overall ergonomics of the API are the best. Because
basically we put the onus on the user of the API to build in locking
while the request is running.
Why would we not make the B*Request objects itself implement a Read()
method? These can be called in the hook functions in the listeners to
'stream' the file/data into the definitive output. It just seems to me
like there will be fewer accidents this way.
I think it just makes things more complicated.
The current API is simple for the simple case. If you want to download
something to a file, you pass a BFile. If you want to download something
to memory, you pass a BDataIO. If you want to download something and do
processing "on the fly" (streaming, for example), you use the new
BMemoryRingIO class which provides the locking. The "download to memory"
and "download to file" cases already cover 90% of uses of the API. The
BMemoryRingIO probably covers 90% of the remaining ones.
So, not only this approach is the simplest, it is also the most flexible
(since you can plug any BDataIO you want) and the most efficient (no extra
copies of the data, no need to juggle the data between multiple threads).
Finally, it is hard to say what will be needed by applications in that
remaining 1% of cases. Would they prefer to be notified for the available
data from a BMessage? Using a pthread lock? a semaphore? A file descriptor
they can use select() on? A blocking read from a BDataIO? It's impossible
to know. So, all we could do to manage threading is provide one interface
which may not cover all cases. That's what BMemoryRingIO does, but it does
it in a way that it is entirely optional, and can be replaced with something
else where needed.
--
Adrien.