I have a setup where myChannel is a Channel[MyData], and myChannel.send is used to feed it chunks of data.
Another thread is attempting to read those chunks using tryRecv.
Although the docs state that tryRecv can fail for "all sorts of reasons", I would intuitively only expect it to fail under normal circumstances when the channel queue is empty. However, in my setup, tryRecv also fails rather frequently when there is plenty of data in the queue for unknown reasons.
Since my MyData objects are 500 kilobytes or so, I suspect that tryRecv fails when the channel is internally locked by myChannel.send. Could someone with knowledge of how this works kindly confirm if this is correct?
Using myChannel.recv (and checking with peek) works fine, but this limits my setup to one reading thread to avoid race conditions. If my theory is correct than what I am looking for is kind of a hybrid between recv and tryRecv- let's call it recvIfQueued for now- where recvIfQueued blocks while the channel is locked for sending, but returns with failure if there is no data, or another error occurs.
If you know of reasons tryRecv can fail for, it would really helpful if you could specify them, so we might get a comprehensive list to put in the docs, peraps eventually with an reason enum for tryRecv, it's really hard to debug the way it is.
Could someone with knowledge of how this works kindly confirm if this is correct?
Confirmed.
If my theory is correct than what I am looking for is kind of a hybrid between recv and tryRecv- let's call it recvIfQueued for now- where recvIfQueued blocks while the channel is locked for sending, but returns with failure if there is no data, or another error occurs.
Why not call peek and then tryRecv instead of recv?
I guess tryRecv also returns false in case it would block due to mutexes. I somehow like it that way, as this can make sure that the amount of blocking is minimal.
But I agree that this isn't the most intuitive behavior. I also expected it to work differently and created some workarounds to make it work the way I tried to. I filled the channels, made a thread pool that read with tryRecv and finished the threads as soon as the channels were empty. I needed to retry, sleep and peek to make sure that I could leave the thread.
For such a use case, I also would have preferred have some variant of tryRecv that actually blocked for a short time instead failing...
Could someone with knowledge of how this works kindly confirm if this is correct?
Confirmed.
Great! Good to know.
Why not call peek and then tryRecv instead of recv?
Because I would still be limited to one receiving thread to avoid race conditions.
I guess tryRecv also returns false in case it would block due to mutexes. I somehow like it that way, as this can make sure that the amount of blocking is minimal.
Yeah I like it too, it's simple. I'd just like the block-only-for-mutex behavior as well.
Using some kind of idiom to construct block-only-for-mutex from the available calls would be fine- I'm staring at the sources right now, but beats me how to do it.