ruby-changes:34769
From: nobu <ko1@a...>
Date: Thu, 17 Jul 2014 19:57:24 +0900 (JST)
Subject: [ruby-changes:34769] nobu:r46852 (trunk): thread/thread.c: non-blocking push on SizedQueue
nobu 2014-07-17 19:57:13 +0900 (Thu, 17 Jul 2014) New Revision: 46852 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=46852 Log: thread/thread.c: non-blocking push on SizedQueue * ext/thread/thread.c (rb_szqueue_push): add optional parameter, non_block defaulted to false. [ruby-core:63794] [Feature #10052] Modified files: trunk/ChangeLog trunk/ext/thread/thread.c trunk/test/thread/test_queue.rb Index: ChangeLog =================================================================== --- ChangeLog (revision 46851) +++ ChangeLog (revision 46852) @@ -1,3 +1,8 @@ https://github.com/ruby/ruby/blob/trunk/ChangeLog#L1 +Thu Jul 17 19:57:27 2014 Herwin <herwin@q...> + + * ext/thread/thread.c (rb_szqueue_push): add optional parameter, + non_block defaulted to false. [ruby-core:63794] [Feature #10052] + Wed Jul 16 23:01:43 2014 Masaki Suketa <masaki.suketa@n...> * ext/win32ole/win32ole.c (ole_variant2val): support array of Index: ext/thread/thread.c =================================================================== --- ext/thread/thread.c (revision 46851) +++ ext/thread/thread.c (revision 46852) @@ -443,30 +443,55 @@ rb_szqueue_max_set(VALUE self, VALUE vma https://github.com/ruby/ruby/blob/trunk/ext/thread/thread.c#L443 return vmax; } +static VALUE +szqueue_push_should_block(int argc, VALUE *argv) +{ + VALUE should_block = Qtrue; + switch (argc) { + case 0: + rb_raise(rb_eArgError, "wrong number of arguments (0 for 1)"); + break; + case 1: + break; + case 2: + should_block = RTEST(argv[1]) ? Qfalse : Qtrue; + break; + default: + rb_raise(rb_eArgError, "wrong number of arguments (%d for 2)", argc); + } + return should_block; +} + /* * Document-method: SizedQueue#push * call-seq: - * push(object) - * enq(object) + * push(object, non_block=false) + * enq(object, non_block=false) * <<(object) * * Pushes +object+ to the queue. * - * If there is no space left in the queue, waits until space becomes available. + * If there is no space left in the queue, waits until space becomes + * available, unless +non_block+ is true. If +non_block+ is true, the + * thread isn't suspended, and an exception is raised. */ static VALUE -rb_szqueue_push(VALUE self, VALUE obj) +rb_szqueue_push(int argc, VALUE *argv, VALUE self) { struct waiting_delete args; + VALUE should_block = szqueue_push_should_block(argc, argv); args.waiting = GET_SZQUEUE_WAITERS(self); args.th = rb_thread_current(); while (queue_length(self) >= GET_SZQUEUE_ULONGMAX(self)) { + if (!(int)should_block) { + rb_raise(rb_eThreadError, "queue full"); + } rb_ary_push(args.waiting, args.th); rb_ensure((VALUE (*)())rb_thread_sleep_deadly, (VALUE)0, queue_delete_from_waiting, (VALUE)&args); } - return queue_do_push(self, obj); + return queue_do_push(self, argv[0]); } static VALUE @@ -609,7 +634,7 @@ Init_thread(void) https://github.com/ruby/ruby/blob/trunk/ext/thread/thread.c#L634 rb_define_method(rb_cSizedQueue, "initialize", rb_szqueue_initialize, 1); 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); + rb_define_method(rb_cSizedQueue, "push", rb_szqueue_push, -1); rb_define_method(rb_cSizedQueue, "pop", rb_szqueue_pop, -1); rb_define_method(rb_cSizedQueue, "clear", rb_szqueue_clear, 0); rb_define_method(rb_cSizedQueue, "num_waiting", rb_szqueue_num_waiting, 0); Index: test/thread/test_queue.rb =================================================================== --- test/thread/test_queue.rb (revision 46851) +++ test/thread/test_queue.rb (revision 46852) @@ -99,6 +99,14 @@ class TestQueue < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/thread/test_queue.rb#L99 def test_sized_queue_push_interrupt q = SizedQueue.new(1) q.push(1) + assert_raise_with_message(ThreadError, /full/) do + q.push(2, true) + end + end + + def test_sized_queue_push_non_block + q = SizedQueue.new(1) + q.push(1) t1 = Thread.new { q.push(2) } sleep 0.01 until t1.stop? t1.kill.join -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/