Getting Default-Initialised Value after Channel is Closed / use std::optional for Popping? #49
Unanswered
stellarpower
asked this question in
Q&A
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
-
Hi,
I think I am repeatedly hitting an issue like the following:
Glossing over the source here I think there may be a potential issue with checking if the channel is closed before acquiring the mutex - it's possible that the channel is open when we check, then the producer closes it, then we acquire the lock. Without having investigated it yet in more detail, I think I'd want to check if the channel is closed again after we acquire the lock. but before I spend any time trying to pin it down and verify if it's a bug, wondering if others are seeing a situation like this in their use of the library, or if the fault is just on my end.
However, as an aside to this, whilst the stream operators are a nice API, I feel that even aside from this specific scenario, it's then hard to tell if there really is a value or not. Let's say the channel is closed in the first check, and we just return. I now have a (presumably) default-initialised value on the stack, and I don't actually know if the channel read anything or not. By streaming into something, we always have a something, whether or not there was a successful pop, so we need a manual method to check the validity of that something.
Personally, I almost always like to use std::optional for this sort of thing. I the existing API works for people, then can leave it as it is, but I think it might be easier to have a function
optional<T> pop()
, where the return value isnullopt
if the channel was closed or empty, or contains a value if the read was successful. Or otherwise we could throw an exception, for those that want to use them, but optional seems lighter to me. So, please do correct me if I'm missing something here, but I think if I do:int latestValue; channel >> latestValue;
then I no have no way of knowing if the read was successful, as
operator>>
just no-ops if there was an issue, soout
is left as it was, and I rely on manually checking that integer to see if it's valid. Potentially meaning that e.g. the value 0 would be out of bounds for values to push, I have to have some sort of empty value I can check for. I can ask the channel if it is closed or empty after the read - but then we have a race condition between the point the pop was performed and the point I perform the check.So, I know boost's lockfree queues return a boolean to indicate success and take by reference in a similar manner, which would achieve the same, but in my own code I always stick to optional (and I'm actually wrapping Channel to do that right now) so that I have a clear idea of if a read was successful or not, and then I don't have to think about it, and I don't get any off-by-one issues downstream. Plus the compiler then enforces me to check the value, whilst a boolean return status can easily be left off and forgotten about.
Thoughts? Thanks!
Beta Was this translation helpful? Give feedback.
All reactions