class Async::Queue

@public Since *Async v1*.
@asynchronous This class is thread-safe.
It has a compatible interface with {Notification} and {Condition}, except that it’s multi-value.
maintaining compatibility with the fiber scheduler.
This implementation uses Thread::Queue internally for thread safety while
A thread-safe queue which allows items to be processed in order.

def <<(item)

Compatibility with {::Queue#push}.
def <<(item)
	self.push(item)
end

def async(parent: (@parent or Task.current), **options, &block)

@yields {|task| ...} When the system is idle, the block will be executed in a new task.
@parameter options [Hash] The options to pass to the task.
@parameter parent [Interface(:async) | Nil] The parent task to use for async operations.
@parameter arguments [Array] The arguments to pass to the block.

@asynchronous Executes the given block concurrently for each item.

Process each item in the queue.
def async(parent: (@parent or Task.current), **options, &block)
	while item = self.dequeue
		parent.async(item, **options, &block)
	end
end

def close

Close the queue, causing all waiting tasks to return `nil`. Any subsequent calls to {enqueue} will raise an exception.
def close
	@delegate.close
end

def closed?

@returns [Boolean] Whether the queue is closed.
def closed?
	@delegate.closed?
end

def dequeue(timeout: nil)

@returns [Object, nil] The dequeued item, or nil if timeout expires.
@parameter timeout [Numeric, nil] Maximum time to wait for an item. If nil, waits indefinitely. If 0, returns immediately.
Remove and return the next item from the queue.
def dequeue(timeout: nil)
	@delegate.pop(timeout: timeout)
end

def each

Enumerate each item in the queue.
def each
	while item = self.dequeue
		yield item
	end
end

def empty?

@returns [Boolean] Whether the queue is empty.
def empty?
	@delegate.empty?
end

def enqueue(*items)

Add multiple items to the queue.
def enqueue(*items)
	items.each {|item| @delegate.push(item)}
rescue ClosedQueueError
	raise ClosedError, "Cannot enqueue items to a closed queue!"
end

def initialize(parent: nil, delegate: Thread::Queue.new)

@parameter parent [Interface(:async) | Nil] The parent task to use for async operations.

Create a new thread-safe queue.
def initialize(parent: nil, delegate: Thread::Queue.new)
	@delegate = delegate
	@parent = parent
end

def pop(timeout: nil)

@returns [Object, nil] The dequeued item, or nil if timeout expires.
@parameter timeout [Numeric, nil] Maximum time to wait for an item. If nil, waits indefinitely. If 0, returns immediately.
Compatibility with {::Queue#pop}.
def pop(timeout: nil)
	@delegate.pop(timeout: timeout)
end

def push(item)

Add an item to the queue.
def push(item)
	@delegate.push(item)
rescue ClosedQueueError
	raise ClosedError, "Cannot enqueue items to a closed queue!"
end

def signal(value = nil)

Signal the queue with a value, the same as {#enqueue}.
def signal(value = nil)
	self.enqueue(value)
end

def size

@returns [Integer] The number of items in the queue.
def size
	@delegate.size
end

def wait

Wait for an item to be available, the same as {#dequeue}.
def wait
	self.dequeue
end

def waiting_count

@returns [Integer] The number of tasks waiting for an item.
def waiting_count
	@delegate.num_waiting
end