| Class | Queue |
| In: |
ext/fastthread/fastthread.c
ext/fastthread/fastthread.c |
| Parent: | Object |
This class provides a way to synchronize communication between threads.
Example:
require 'thread'
queue = Queue.new
producer = Thread.new do
5.times do |i|
sleep rand(i) # simulate expense
queue << i
puts "#{i} produced"
end
end
consumer = Thread.new do
5.times do |i|
value = queue.pop
sleep rand(i/2) # simulate expense
puts "consumed #{value}"
end
end
consumer.join
Removes all objects from the queue.
/*
* Document-method: clear
* call-seq: clear
*
* Removes all objects from the queue.
*
*/
static VALUE
rb_queue_clear(VALUE self)
{
Queue *queue;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
clear_list(&queue->values);
signal_condvar(&queue->space_available);
unlock_mutex(&queue->mutex);
return self;
}
Removes all objects from the queue.
/*
* Document-method: clear
* call-seq: clear
*
* Removes all objects from the queue.
*
*/
static VALUE
rb_queue_clear(VALUE self)
{
Queue *queue;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
clear_list(&queue->values);
signal_condvar(&queue->space_available);
unlock_mutex(&queue->mutex);
return self;
}
Returns true if the queue is empty.
/*
* Document-method: empty?
* call-seq: empty?
*
* Returns +true+ if the queue is empty.
*
*/
static VALUE
rb_queue_empty_p(VALUE self)
{
Queue *queue;
VALUE result;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
result = queue->values.size == 0 ? Qtrue : Qfalse;
unlock_mutex(&queue->mutex);
return result;
}
Returns true if the queue is empty.
/*
* Document-method: empty?
* call-seq: empty?
*
* Returns +true+ if the queue is empty.
*
*/
static VALUE
rb_queue_empty_p(VALUE self)
{
Queue *queue;
VALUE result;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
result = queue->values.size == 0 ? Qtrue : Qfalse;
unlock_mutex(&queue->mutex);
return result;
}
Returns the length of the queue.
/*
* Document-method: length
* call-seq: length
*
* Returns the length of the queue.
*
*/
static VALUE
rb_queue_length(VALUE self)
{
Queue *queue;
VALUE result;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
result = ULONG2NUM(queue->values.size);
unlock_mutex(&queue->mutex);
return result;
}
Returns the length of the queue.
/*
* Document-method: length
* call-seq: length
*
* Returns the length of the queue.
*
*/
static VALUE
rb_queue_length(VALUE self)
{
Queue *queue;
VALUE result;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
result = ULONG2NUM(queue->values.size);
unlock_mutex(&queue->mutex);
return result;
}
Returns the number of threads waiting on the queue.
/*
* Document-method: num_waiting
* call-seq: num_waiting
*
* Returns the number of threads waiting on the queue.
*
*/
static VALUE
rb_queue_num_waiting(VALUE self)
{
Queue *queue;
VALUE result;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
result = ULONG2NUM(queue->value_available.waiting.size +
queue->space_available.waiting.size);
unlock_mutex(&queue->mutex);
return result;
}
Returns the number of threads waiting on the queue.
/*
* Document-method: num_waiting
* call-seq: num_waiting
*
* Returns the number of threads waiting on the queue.
*
*/
static VALUE
rb_queue_num_waiting(VALUE self)
{
Queue *queue;
VALUE result;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
result = ULONG2NUM(queue->value_available.waiting.size +
queue->space_available.waiting.size);
unlock_mutex(&queue->mutex);
return result;
}
call_seq: pop(non_block=false)
Retrieves data from the queue. If the queue is empty, the calling thread is suspended until data is pushed onto the queue. If non_block is true, the thread isn‘t suspended, and an exception is raised.
/*
* Document-method: pop
* call_seq: pop(non_block=false)
*
* Retrieves data from the queue. If the queue is empty, the calling thread is
* suspended until data is pushed onto the queue. If +non_block+ is true, the
* thread isn't suspended, and an exception is raised.
*
*/
static VALUE
rb_queue_pop(int argc, VALUE *argv, VALUE self)
{
Queue *queue;
int should_block;
VALUE result;
Data_Get_Struct(self, Queue, queue);
if (argc == 0) {
should_block = 1;
} else if (argc == 1) {
should_block = !RTEST(argv[0]);
} else {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
}
lock_mutex(&queue->mutex);
if (!queue->values.entries && !should_block) {
unlock_mutex(&queue->mutex);
rb_raise(private_eThreadError, "queue empty");
}
while (!queue->values.entries) {
wait_condvar(&queue->value_available, &queue->mutex);
}
result = shift_list(&queue->values);
if (queue->capacity && queue->values.size < queue->capacity) {
signal_condvar(&queue->space_available);
}
unlock_mutex(&queue->mutex);
return result;
}
call_seq: pop(non_block=false)
Retrieves data from the queue. If the queue is empty, the calling thread is suspended until data is pushed onto the queue. If non_block is true, the thread isn‘t suspended, and an exception is raised.
/*
* Document-method: pop
* call_seq: pop(non_block=false)
*
* Retrieves data from the queue. If the queue is empty, the calling thread is
* suspended until data is pushed onto the queue. If +non_block+ is true, the
* thread isn't suspended, and an exception is raised.
*
*/
static VALUE
rb_queue_pop(int argc, VALUE *argv, VALUE self)
{
Queue *queue;
int should_block;
VALUE result;
Data_Get_Struct(self, Queue, queue);
if (argc == 0) {
should_block = 1;
} else if (argc == 1) {
should_block = !RTEST(argv[0]);
} else {
rb_raise(rb_eArgError, "wrong number of arguments (%d for 1)", argc);
}
lock_mutex(&queue->mutex);
if (!queue->values.entries && !should_block) {
unlock_mutex(&queue->mutex);
rb_raise(private_eThreadError, "queue empty");
}
while (!queue->values.entries) {
wait_condvar(&queue->value_available, &queue->mutex);
}
result = shift_list(&queue->values);
if (queue->capacity && queue->values.size < queue->capacity) {
signal_condvar(&queue->space_available);
}
unlock_mutex(&queue->mutex);
return result;
}
Pushes obj to the queue.
/*
* Document-method: push
* call-seq: push(obj)
*
* Pushes +obj+ to the queue.
*
*/
static VALUE
rb_queue_push(VALUE self, VALUE value)
{
Queue *queue;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
while (queue->capacity && queue->values.size >= queue->capacity) {
wait_condvar(&queue->space_available, &queue->mutex);
}
push_list(&queue->values, value);
signal_condvar(&queue->value_available);
unlock_mutex(&queue->mutex);
return self;
}
Pushes obj to the queue.
/*
* Document-method: push
* call-seq: push(obj)
*
* Pushes +obj+ to the queue.
*
*/
static VALUE
rb_queue_push(VALUE self, VALUE value)
{
Queue *queue;
Data_Get_Struct(self, Queue, queue);
lock_mutex(&queue->mutex);
while (queue->capacity && queue->values.size >= queue->capacity) {
wait_condvar(&queue->space_available, &queue->mutex);
}
push_list(&queue->values, value);
signal_condvar(&queue->value_available);
unlock_mutex(&queue->mutex);
return self;
}