diff options
author | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-07-17 10:57:13 +0000 |
---|---|---|
committer | nobu <nobu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2014-07-17 10:57:13 +0000 |
commit | 4c849f0e6252545697da3a0466ff536cf241e05f (patch) | |
tree | 1e03401bf9160597a4e8ab72b0166f0cb1f0f219 /ext/thread/thread.c | |
parent | 06e70ae4f3c64d24539bd434b278e7cd8e7e1002 (diff) | |
download | ruby-4c849f0e6252545697da3a0466ff536cf241e05f.tar.gz |
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]
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@46852 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'ext/thread/thread.c')
-rw-r--r-- | ext/thread/thread.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/ext/thread/thread.c b/ext/thread/thread.c index 38b8a8c4e7..1f4149afbe 100644 --- a/ext/thread/thread.c +++ b/ext/thread/thread.c @@ -443,30 +443,55 @@ rb_szqueue_max_set(VALUE self, VALUE vmax) 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) 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); |