mirror of
https://github.com/mruby/mruby
synced 2026-06-08 16:11:16 +00:00
458078f10e
- This patch implements `Task::Queue` mirroring `Thread::Queue` in CRuby. - Producer/Consumer pattern is now possible with no polling ## No Top-level pollution - No top-level `Queue` defined - No `TaskError`. Instead, `Task::Error` happens when `Task::Queue#pop(true)` when empty - No `ClosedQueueError`. `Task::Error` also happens when pushing to closed queue ## Future Work - `Task::SizedQueue`
31 lines
956 B
Ruby
31 lines
956 B
Ruby
class Task
|
|
class Queue
|
|
# WAIT_RETRY is defined in C (task_queue.c gem init)
|
|
|
|
def push(obj)
|
|
__push(obj)
|
|
self
|
|
end
|
|
alias enq push
|
|
alias << push
|
|
|
|
# Blocks until an item is available (default), or raises if non_block is true.
|
|
# Returns nil if the queue is closed and empty.
|
|
#
|
|
# The loop is not a busy-wait. When __pop_try finds the queue empty it moves
|
|
# the current task to WAITING and sets switching_=TRUE before returning
|
|
# WAIT_RETRY. The VM detects switching_ at the next opcode boundary and
|
|
# exits mrb_vm_exec, handing control back to the scheduler. This task does
|
|
# not run again until a push (or close) moves it back to READY. The loop
|
|
# body therefore executes at most once per wakeup event.
|
|
def pop(non_block = false)
|
|
loop do
|
|
v = __pop_try(non_block)
|
|
return v unless v.equal?(WAIT_RETRY)
|
|
end
|
|
end
|
|
alias deq pop
|
|
alias shift pop
|
|
end
|
|
end
|