Project

General

Profile

Actions

Feature #19905

open

Introduce `Queue#peek`

Added by hi@joaofernandes.me (Joao Fernandes) 7 months ago. Updated 2 months ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:114915]

Description

This ticket proposes the introduction of the Queue#peek method, similar to what we can find in other object oriented languages such as Java and C#. This method is similar to Queue#pop, but does not change the data, nor does it require a lock.

q = Queue.new([1,2,3])
=> #<Thread::Queue:0x00000001065d7148>
q.peek
=> 1
q.peek
=> 1

I have felt the need of this for debugging, but I think that it can also be of practical use for presentation. I believe that the only drawback could be that newcomers could misuse it in multi-threaded work without taking into account that this method is not thread safe.

I also volunteer myself to implement this method.

Updated by ko1 (Koichi Sasada) 7 months ago

Could you describe more about use cases?

Updated by hi@joaofernandes.me (Joao Fernandes) 7 months ago

ko1 (Koichi Sasada) wrote in #note-1:

Could you describe more about use cases?

My main use case for this feature is observability and debugging. For example, I am experimenting with a car pooling simulation where multiple queues of passengers exist. I want to track the length of each queue, and how long the first passenger of each queue has been waiting. Thus, I would like to look at the first element of each queue without removing it, so that the workers can pick it up.

I was also considering using this method to decide which queue to serve first. While I would still need to be careful with concurrency issues for this feature, #peek would be extremely helpful.

Does this clarify potential use cases? Does it seem like a potential good addition to the language?

Updated by shan (Shannon Skipper) 7 months ago

I'm just curious if it might be better for #peek to lock to avoid showing something that has already popped or other parallel access issues? Is there significant advantage having it not lock?

Updated by Eregon (Benoit Daloze) 7 months ago

peek is inherently racy in that the value observed might be already popped by the time the value is returned.
If it's for observability and debugging I think to_a or each makes more sense, it's for sure useful to see other values than just the first one.

Updated by sidonath (Damir Zekic) 2 months ago

I would like to provide another use case for Queue#peek. I'm using Queue in a project that's running commands prone to failures. I have a queue of commands, a worker and a monitor threads. The worker pops the commands, runs them in sequence and the monitor thread reports on the activity and restarts the worker if it observes a failure. Having ability to "peek" into the command list would allow informative output about what is the next command that will be executed. Obviously, having #to_a or #each would be as helpful here. The queue is not long for me to worry about looking up all elements versus the first one.

If there's a race condition and the proposed #peek doesn't lock, then the display of the "next command" might be briefly inaccurate at times, but that's not something I would consider an issue in this project. If it were locking, then I would need to use the retrieved instance outside of the locked block. This would beat the purpose of the lock, but that would be the conscious choice of me as the author of the code. I guess whether #peek locks or not would not be important in my situation.

Updated by byroot (Jean Boussier) 2 months ago

Seems like all the use cases so far would be as well if not better handled by to_a. Which I admit I hoped existed a few times when debugging code that uses Queue. Should also be relatively straightforward to implement.

Updated by ko1 (Koichi Sasada) 2 months ago

I feel it is natural that to_a returns [] immediately if there is no enqueued item.
(#peek is not clear on it)

Actions

Also available in: Atom PDF

Like2
Like0Like1Like0Like0Like0Like1Like0