Feature #17357
open`Queue#pop` should have a block form for closed queues
Description
It is currently difficult to reliably distinguish a nil
value in a queue from the nil
that is returned when a Queue is closed:
n = 100_000
result = []
t2 = Thread.new { n.times { Thread.pass }} # to make things less predictable
n.times.count do
q = Queue.new
t = Thread.new { q.pop; result << q.closed? }
q << nil
q.close
t.join
end
puts result.count(true) # => some number usually > 9990 and < 10000
To be completely sure, one needs a Mutex or wrap/unwrap nil
values.
Queue#pop
should offer a surefire way to handle closed queues. I propose that an optional block be called in this case:
q = Queue.new.close
q.pop # => nil
q.pop { :closed } # => :closed
Proposed PR: https://github.com/ruby/ruby/pull/3830
Updated by mame (Yusuke Endoh) almost 4 years ago
- Related to Feature #10600: [PATCH] Queue#close added
Updated by naruse (Yui NARUSE) almost 4 years ago
- Status changed from Open to Feedback
Do you have a use case?
The issue is well discussed in [Feature #10600] and concluded as current spec.
To discuss again we need new materials.
Updated by marcandre (Marc-Andre Lafortune) almost 4 years ago
- Status changed from Feedback to Open
General use case: using Queue
for objects that might be nil
.
Why I opened this issue? I am writing a pure-Ruby backport of Ractor (using Thread
). I am using Queue
for messaging queues. nil
can be value sent / received by Ractors (e.g. Ractor.yield
). Can also be the final result of a ractor block. I need to store this in Queue.
So to be safe, I need to wrap/unwrap nil
values.
My concern is same as with timeout:
option: we have an "easy" way to do something that works 99%+ of the time, but is not 100% safe. Currently the only 100% way is difficult. People are lazy. We need to give easy 100% solution.
Updated by marcandre (Marc-Andre Lafortune) almost 4 years ago
Final note:
- no particular justification was given for choosing not to differentiate
nil
and closed result at the time. - many APIs were proposed (raising, or keyword parameters). Keyword parameters were a "no" because they were slow. I imagine that is no longer the case.
Let's make Ruby safe.
Updated by Dan0042 (Daniel DeLorme) almost 4 years ago
If this is accepted I think it would be good to have the same API as Hash#fetch, with both argument and block forms. For consistency.
edit: oops, I didn't realize that Queue#pop
already has a non_block
optional argument.
Updated by znz (Kazuhiro NISHIYAMA) almost 4 years ago
- Subject changed from `Queue#pop` should have a block form for clsoed queues to `Queue#pop` should have a block form for closed queues