Feature #11517 ยป ruby_queue_conditional_pop.patch
| ChangeLog (working copy) | ||
|---|---|---|
| 
     Tue Sep  9 02:33:45 2015  Jonathan Cruz  <jcruz@trustwave.com> 
   | 
||
| 
     	* thread_sync.c: Update Queue#pop(should_block=true) 
   | 
||
| 
     	  Allow the caller to provide a block that accepts data from the 
   | 
||
| 
     	  queue. Return the first element for which the block returns a 
   | 
||
| 
     	  truthy value, and remove it from the queue. 
   | 
||
| 
     Thu Sep  3 21:12:12 2015  Nobuyoshi Nakada  <nobu@ruby-lang.org> 
   | 
||
| 
     	* lib/cgi/session.rb (create_new_id): use SHA512 instead of MD5. 
   | 
||
| thread_sync.c (working copy) | ||
|---|---|---|
| 
     static VALUE 
   | 
||
| 
     queue_do_pop(VALUE self, int should_block) 
   | 
||
| 
     { 
   | 
||
| 
         VALUE que = GET_QUEUE_QUE(self); 
   | 
||
| 
         struct waiting_delete args; 
   | 
||
| 
         args.waiting = GET_QUEUE_WAITERS(self); 
   | 
||
| 
         args.th	 = rb_thread_current(); 
   | 
||
| 
         while (queue_length(self) == 0) { 
   | 
||
| 
     	if (!should_block) { 
   | 
||
| 
     	    rb_raise(rb_eThreadError, "queue empty"); 
   | 
||
| 
     	} 
   | 
||
| 
     	else if (queue_closed_p(self)) { 
   | 
||
| 
     	    return queue_closed_result(self); 
   | 
||
| 
     	} 
   | 
||
| 
     	else { 
   | 
||
| 
     	    assert(queue_length(self) == 0); 
   | 
||
| 
     	    assert(queue_closed_p(self) == 0); 
   | 
||
| 
        for(;;) { 
   | 
||
| 
             VALUE obj = 0; 
   | 
||
| 
             int obj_index = -1; 
   | 
||
| 
     	    rb_ary_push(args.waiting, args.th); 
   | 
||
| 
     	    rb_ensure(queue_sleep, (VALUE)0, queue_delete_from_waiting, (VALUE)&args); 
   | 
||
| 
     	} 
   | 
||
| 
             if (rb_block_given_p()) { 
   | 
||
| 
                 for (i=0; i < RARRAY_LEN(que); i++) { 
   | 
||
| 
                     obj = RARRAY_AREF(que, i) 
   | 
||
| 
                     if (rb_yield(obj)) { 
   | 
||
| 
                         obj_index = i; 
   | 
||
| 
                         break; 
   | 
||
| 
                     } 
   | 
||
| 
                 } 
   | 
||
| 
             } 
   | 
||
| 
             else if (RARRAY_LEN(que) > 0) { 
   | 
||
| 
                 return rb_ary_shift(que); 
   | 
||
| 
             } 
   | 
||
| 
             if (obj_index >= 0) { 
   | 
||
| 
                 rb_ary_delete_at(que, obj_index); 
   | 
||
| 
                 return obj; 
   | 
||
| 
             } 
   | 
||
| 
             if (!should_block) { 
   | 
||
| 
                 rb_raise(rb_eThreadError, "queue empty"); 
   | 
||
| 
             } 
   | 
||
| 
             else if (queue_closed_p(self)) { 
   | 
||
| 
                 return queue_closed_result(self); 
   | 
||
| 
             } 
   | 
||
| 
             else { 
   | 
||
| 
                 assert(queue_length(self) == 0); 
   | 
||
| 
                 assert(queue_closed_p(self) == 0); 
   | 
||
| 
                 rb_ary_push(args.waiting, args.th); 
   | 
||
| 
                 rb_ensure(queue_sleep, (VALUE)0, queue_delete_from_waiting, (VALUE)&args); 
   | 
||
| 
             } 
   | 
||
| 
         } 
   | 
||
| 
         return rb_ary_shift(GET_QUEUE_QUE(self)); 
   | 
||
| 
     } 
   | 
||
| 
     static int 
   | 
||
| ... | ... | |
| 
      *   deq(non_block=false) 
   | 
||
| 
      *   shift(non_block=false) 
   | 
||
| 
      * 
   | 
||
| 
      * Retrieves data from the queue. 
   | 
||
| 
      * Retrieves data from the queue. If +block+ is given, retrieves data from the 
   | 
||
| 
      * queue for which the given +block+ returns a true value. 
   | 
||
| 
      * 
   | 
||
| 
      * 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. 
   | 
||
| 
      * If the queue is empty (or +block+ never returns true), 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 
   | 
||
| ... | ... | |
| 
      *   deq(non_block=false) 
   | 
||
| 
      *   shift(non_block=false) 
   | 
||
| 
      * 
   | 
||
| 
      * Retrieves data from the queue. 
   | 
||
| 
      * Retrieves data from the queue. If +block+ is given, retrieves data from the 
   | 
||
| 
      * queue for which the given +block+ returns a true value. 
   | 
||
| 
      * 
   | 
||
| 
      * 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. 
   | 
||
| 
      * If the queue is empty (or +block+ never returns true), 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 
   | 
||