Index: ChangeLog =================================================================== --- ChangeLog (revision 51752) +++ ChangeLog (working copy) @@ -1,3 +1,11 @@ +Tue Sep 9 02:43:13 2015 Jonathan Cruz + + * thread_sync.c: Add Queue#promote! and Queue#promote_all! + Promotes elements to the front of the queue for which the provided + block returns a truthy value. #promote! only applies to the first + such element. #promote_all! applies to all matching elements, + maintaining their relative order. + Thu Sep 3 21:12:12 2015 Nobuyoshi Nakada * lib/cgi/session.rb (create_new_id): use SHA512 instead of MD5. Index: thread_sync.c =================================================================== --- thread_sync.c (revision 51752) +++ thread_sync.c (working copy) @@ -905,6 +905,64 @@ } /* + * Document-method: Queue#promote! + * call-seq: promote! + * + * Promotes first object to the front of the queue for which the given +block+ + * returns a true value. + */ + +static VALUE +rb_queue_promote(VALUE self) +{ + if (!rb_block_given_p()) { + rb_raise(rb_eThreadError, "must be called with a block"); + } + return queue_do_promote(self, FALSE); +} + +/* + * Document-method: Queue#promote_all! + * call-seq: promote_all! + * + * + * Promotes all objects to the front of the queue for which the given +block+ + * returns a true value, preserving their relative order. + */ + +static VALUE +rb_queue_promote_all(VALUE self) +{ + if (!rb_block_given_p()) { + rb_raise(rb_eThreadError, "must be called with a block"); + } + return queue_do_promote(self, TRUE); +} + +static VALUE +queue_do_promote(VALUE self, int promote_all) +{ + VALUE que = GET_QUEUE_QUE(self); + VALUE promote = rb_ary_new2(RARRAY_LEN(que)); + long i; + for (i = 0; i < RARRAY_LEN(que); i++) { + VALUE obj = RARRAY_AREF(que, i); + if (RTEST(rb_yield(obj))) { + rb_ary_unshift(promote, obj); + if (!promote_all) break; + } + } + + for (i = 0; i < RARRAY_LEN(promote); i++) { + VALUE obj = RARRAY_AREF(promote, i); + rb_ary_delete(que, obj); + rb_ary_unshift(que, obj); + } + return self; +} + + +/* * Document-class: SizedQueue * * This class represents queues of specified size capacity. The push operation @@ -1281,6 +1339,8 @@ rb_define_method(rb_cQueue, "clear", rb_queue_clear, 0); rb_define_method(rb_cQueue, "length", rb_queue_length, 0); rb_define_method(rb_cQueue, "num_waiting", rb_queue_num_waiting, 0); + rb_define_method(rb_cQueue, "promote!", rb_queue_promote, 0); + rb_define_method(rb_cQueue, "promote_all!", rb_queue_promote_all, 0); rb_define_alias(rb_cQueue, "enq", "push"); /* Alias for #push. */ rb_define_alias(rb_cQueue, "<<", "push"); /* Alias for #push. */