aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--test/thread/test_queue.rb32
-rw-r--r--thread_sync.c44
3 files changed, 23 insertions, 62 deletions
diff --git a/ChangeLog b/ChangeLog
index 8c1d6ff2ac..01e5decaaa 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+Sat Nov 21 09:18:10 2015 Koichi Sasada <ko1@atdot.net>
+
+ * thread_sync.c: reduce the specification of Queue#close.
+ * Queue#close accepts no arguments.
+ * deq'ing on closed queue returns nil, always.
+ [Feature #10600]
+
+ * test/thread/test_queue.rb: catch up this fix.
+
Sat Nov 21 08:44:21 2015 Koichi Sasada <ko1@atdot.net>
* compile.c (iseq_compile_each): add debug information to NODE_STR
diff --git a/test/thread/test_queue.rb b/test/thread/test_queue.rb
index 13cefde641..59d51e730c 100644
--- a/test/thread/test_queue.rb
+++ b/test/thread/test_queue.rb
@@ -289,6 +289,7 @@ class TestQueue < Test::Unit::TestCase
assert_raise_with_message(ClosedQueueError, /closed/){q << :nothing}
assert_equal q.pop, :something
assert_nil q.pop
+ assert_nil q.pop
# non-blocking
assert_raise_with_message(ThreadError, /queue empty/){q.pop(non_block=true)}
end
@@ -484,36 +485,11 @@ class TestQueue < Test::Unit::TestCase
assert_nil t.value
end
- def test_close_token_exception
- [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate|
- q = qcreate[]
- q.close true
- assert_raise(ClosedQueueError){q.pop}
- end
- end
-
- def test_close_token_loop
- [->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate|
- q = qcreate[]
- popped_items = []
- consumer_thread = Thread.new{loop{popped_items << q.pop}; :done}
- 7.times{|i| q << i}
- q.close true
- sleep 0.1 unless q.empty?
- assert_equal :done, consumer_thread.value
- assert_equal 7.times.to_a, popped_items
- end
- end
-
def test_close_twice
[->{Queue.new}, ->{SizedQueue.new 3}].each do |qcreate|
q = qcreate[]
q.close
assert_nothing_raised(ClosedQueueError){q.close}
-
- q = qcreate[]
- q.close(true)
- assert_nothing_raised(ClosedQueueError){q.close(false)}
end
end
@@ -533,8 +509,8 @@ class TestQueue < Test::Unit::TestCase
consumers = rand(7..12).times.map do
Thread.new do
count = 0
- loop do
- i, st = q.pop
+ while e = q.pop
+ i, st = e
count += 1 if i.is_a?(Fixnum) && st.is_a?(String)
end
count
@@ -554,7 +530,7 @@ class TestQueue < Test::Unit::TestCase
end
producers.each &:join
- q.close true
+ q.close
# results not randomly distributed. Not sure why.
# consumers.map{|thr| thr.value}.each do |x|
diff --git a/thread_sync.c b/thread_sync.c
index 6778e3baa9..673ed60aff 100644
--- a/thread_sync.c
+++ b/thread_sync.c
@@ -523,7 +523,6 @@ enum {
};
#define QUEUE_CLOSED FL_USER5
-#define QUEUE_CLOSE_EXCEPTION FL_USER6
#define GET_QUEUE_QUE(q) get_array((q), QUEUE_QUE)
#define GET_QUEUE_WAITERS(q) get_array((q), QUEUE_WAITERS)
@@ -607,26 +606,15 @@ static VALUE
queue_closed_result(VALUE self)
{
assert(queue_length(self) == 0);
-
- if (FL_TEST(self, QUEUE_CLOSE_EXCEPTION)) {
- raise_closed_queue_error(self);
- }
return Qnil;
}
static VALUE
-queue_do_close(VALUE self, int argc, VALUE *argv, int is_szq)
+queue_do_close(VALUE self, int is_szq)
{
- VALUE exception = Qfalse;
-
if (!queue_closed_p(self)) {
- rb_scan_args(argc, argv, "01", &exception);
FL_SET(self, QUEUE_CLOSED);
- if (RTEST(exception)) {
- FL_SET(self, QUEUE_CLOSE_EXCEPTION);
- }
-
if (queue_num_waiting(self) > 0) {
VALUE waiters = GET_QUEUE_WAITERS(self);
wakeup_all_threads(waiters);
@@ -697,7 +685,7 @@ queue_do_push(VALUE self, VALUE obj)
/*
* Document-method: Queue#close
* call-seq:
- * close(exception=false)
+ * close
*
* Closes the queue. A closed queue cannot be re-opened.
*
@@ -707,15 +695,11 @@ queue_do_push(VALUE self, VALUE obj)
*
* - +close+ will be ignored.
*
- * - calling enq/push/<< will raise ClosedQueueError('queue closed')
+ * - calling enq/push/<< will return nil.
*
* - when +empty?+ is false, calling deq/pop/shift will return an object
* from the queue as usual.
*
- * - when +empty?+ is true, deq(non_block=false) will not suspend and
- * will either return nil. If +exception+ parameter is true, raise ClosedQueueError error.
- * deq(non_block=true) will ignore the parameter and raise a ThreadError('queue empty').
- *
* ClosedQueueError is inherited from StopIteration, so that you can break loop block.
*
* Example:
@@ -726,21 +710,13 @@ queue_do_push(VALUE self, VALUE obj)
* # ...
* end
* }
- * q.close # equals to q.close(false)
- *
- * q = Queue.new
- * Thread.new{
- * loop{
- * e = q.deq; ... # break with ClosedQueueError
- * }
- * }
- * q.close(true)
+ * q.close
*/
static VALUE
-rb_queue_close(int argc, VALUE *argv, VALUE self)
+rb_queue_close(VALUE self)
{
- return queue_do_close(self, argc, argv, FALSE);
+ return queue_do_close(self, FALSE);
}
/*
@@ -951,9 +927,9 @@ rb_szqueue_initialize(VALUE self, VALUE vmax)
* raising ClosedQueueError('queue closed').
*/
static VALUE
-rb_szqueue_close(int argc, VALUE *argv, VALUE self)
+rb_szqueue_close(VALUE self)
{
- return queue_do_close(self, argc, argv, TRUE);
+ return queue_do_close(self, TRUE);
}
/*
@@ -1273,7 +1249,7 @@ Init_thread_sync(void)
rb_define_method(rb_cQueue, "initialize", rb_queue_initialize, 0);
rb_undef_method(rb_cQueue, "initialize_copy");
rb_define_method(rb_cQueue, "marshal_dump", undumpable, 0);
- rb_define_method(rb_cQueue, "close", rb_queue_close, -1);
+ rb_define_method(rb_cQueue, "close", rb_queue_close, 0);
rb_define_method(rb_cQueue, "closed?", rb_queue_closed_p, 0);
rb_define_method(rb_cQueue, "push", rb_queue_push, 1);
rb_define_method(rb_cQueue, "pop", rb_queue_pop, -1);
@@ -1294,7 +1270,7 @@ Init_thread_sync(void)
"que", "waiters", "queue_waiters", "size", NULL);
rb_define_method(rb_cSizedQueue, "initialize", rb_szqueue_initialize, 1);
- rb_define_method(rb_cSizedQueue, "close", rb_szqueue_close, -1);
+ rb_define_method(rb_cSizedQueue, "close", rb_szqueue_close, 0);
rb_define_method(rb_cSizedQueue, "max", rb_szqueue_max_get, 0);
rb_define_method(rb_cSizedQueue, "max=", rb_szqueue_max_set, 1);
rb_define_method(rb_cSizedQueue, "push", rb_szqueue_push, -1);