pop (SizedQueue)

    /*
     * 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;
    }