Feature #9145

Queue#pop(true) return nil if empty instead of raising ThreadError

Added by Justin Collins almost 2 years ago. Updated almost 2 years ago.

[ruby-core:58545]
Status:Feedback
Priority:Normal
Assignee:-

Description

I propose the non-blocking form of Queue#pop behave like Array#pop and return nil when empty.

Current behavior is to raise a ThreadError, with a message indicating the queue is empty.

For example:

q = Queue.new
begin
loop do
next_item = q.pop(true)
end
rescue ThreadError
# queue is empty...or maybe something bad happened
end

Instead, this could be

q = Queue.new
while next_item = q.pop(true)
end

Alternatively, raise an exception that is a subclass of ThreadError with a more specific name, such as "QueueEmpty". This would be a small improvement while remaining compatible with existing code.

History

#1 Updated by Masaki Matsushita almost 2 years ago

  • Category changed from lib to ext
  • Status changed from Open to Feedback

I think we can't change default behavior of Queue#pop(true) because some code expects ThreadError to be raised.
However, it may be possible to introduce new keyword argument like following:

q = Queue.new
while next_item = q.pop(true, exception: false) # it doesn't raise ThreadError and returns nil.
# do something
end

#2 Updated by Eric Wong almost 2 years ago

"Glass_saga (Masaki Matsushita)" glass.saga@gmail.com wrote:

I think we can't change default behavior of Queue#pop(true) because some code expects ThreadError to be raised.
However, it may be possible to introduce new keyword argument like following:

q = Queue.new
while next_item = q.pop(true, exception: false) # it doesn't raise ThreadError and returns nil.
# do something
end

+1 to that. All non-blocking methods (I/O or not) should support
exception: false to avoid (expensive/noisy-on-$DEBUG=$true) exceptions.

#3 Updated by Justin Collins almost 2 years ago

Glass_saga (Masaki Matsushita) wrote:

I think we can't change default behavior of Queue#pop(true) because some code expects ThreadError to be raised.
However, it may be possible to introduce new keyword argument like following:

q = Queue.new
while next_item = q.pop(true, exception: false) # it doesn't raise ThreadError and returns nil.
# do something
end

That would work for me.

#4 Updated by Anonymous almost 2 years ago

On 11/23/2013 08:30 PM, Glass_saga (Masaki Matsushita) wrote:

I think we can't change default behavior of Queue#pop(true) because some code expects ThreadError to be raised.
However, it may be possible to introduce new keyword argument like following:

q = Queue.new
while next_item = q.pop(true, exception: false) # it doesn't raise ThreadError and returns nil.
# do something
end

Or what about a new method, Queue#pop?, which is always non-blocking and
non-raising. It would behave like:

class Queue
def pop?
pop(true)
rescue ThreadError
nil
end
end

q = Queue.new

q << 1
q << 2
q << 3

while x=q.pop?
p x
end

END
output:
1
2
3

#5 Updated by Eric Hodel almost 2 years ago

Note that the current behavior allows you to distinguish between a nil in the queue (returns nil) and no value in the queue (raises ThreadError)

Also available in: Atom PDF