Bug #4266 » monitor-synchronize-use-c-implementation.patch
| ext/monitor/extconf.rb | ||
|---|---|---|
| 
     require 'mkmf' 
   | 
||
| 
     target = "monitor_mixin" 
   | 
||
| 
     create_makefile(target) 
   | 
||
| ext/monitor/monitor_mixin.c | ||
|---|---|---|
| 
     /********************************************************************** 
   | 
||
| 
       monitor_mixin.c - 
   | 
||
| 
       $Author: Brian Gugliemetti $ 
   | 
||
| 
       created at: Wed Apr 27 14:51:06 CST 2011 
   | 
||
| 
       All the files in this distribution are covered under the Ruby's 
   | 
||
| 
       license (see the file COPYING). 
   | 
||
| 
     **********************************************************************/ 
   | 
||
| 
     #include "ruby.h" 
   | 
||
| 
     static VALUE rb_mon_enter _((VALUE monitor)); 
   | 
||
| 
     static VALUE rb_mon_exit _((VALUE monitor)); 
   | 
||
| 
     static VALUE rb_mon_check_owner _((VALUE monitor)); 
   | 
||
| 
     static VALUE rb_mon_synchronize _((VALUE monitor, VALUE (*func)(VALUE arg), VALUE arg)); 
   | 
||
| 
     void Init_monitor_mixin _((void)); 
   | 
||
| 
     VALUE rb_mMonitorMixin; 
   | 
||
| 
     /* 
   | 
||
| 
      * MonitorMixin methods 
   | 
||
| 
      */ 
   | 
||
| 
     VALUE 
   | 
||
| 
     rb_mon_check_owner(VALUE monitor) 
   | 
||
| 
     { 
   | 
||
| 
     	VALUE mon_owner = rb_ivar_get(monitor, rb_intern("@mon_owner")); 
   | 
||
| 
     	VALUE th = rb_thread_current(); 
   | 
||
| 
     	if (mon_owner != th) 
   | 
||
| 
     	{ 
   | 
||
| 
     		rb_raise(rb_eThreadError, "current thread not owner"); 
   | 
||
| 
     	} 
   | 
||
| 
     } 
   | 
||
| 
     /* 
   | 
||
| 
      * call-seq: 
   | 
||
| 
      *   monitor_mixin.mon_enter -> int 
   | 
||
| 
      * 
   | 
||
| 
      * Returns number of times the monitor has entered. 
   | 
||
| 
      */ 
   | 
||
| 
     VALUE 
   | 
||
| 
     rb_mon_enter(VALUE monitor) 
   | 
||
| 
     { 
   | 
||
| 
     	VALUE mon_owner = rb_ivar_get(monitor, rb_intern("@mon_owner")); 
   | 
||
| 
     	VALUE mon_mutex = rb_ivar_get(monitor, rb_intern("@mon_mutex")); 
   | 
||
| 
     	VALUE mon_count; 
   | 
||
| 
     	ID mon_count_id; 
   | 
||
| 
     	VALUE th = rb_thread_current(); 
   | 
||
| 
     	if (mon_owner != th) 
   | 
||
| 
     	{ 
   | 
||
| 
     		rb_mutex_lock(mon_mutex); 
   | 
||
| 
     		rb_ivar_set(monitor, rb_intern("@mon_owner"), th); 
   | 
||
| 
     	} 
   | 
||
| 
     	mon_count = rb_ivar_get(monitor, mon_count_id = rb_intern("@mon_count")); 
   | 
||
| 
     	rb_ivar_set(monitor, mon_count_id, mon_count = INT2NUM(NUM2INT(mon_count) + 1)); 
   | 
||
| 
     	return mon_count; 
   | 
||
| 
     } 
   | 
||
| 
     VALUE 
   | 
||
| 
     rb_mon_exit_no_check(VALUE monitor) 
   | 
||
| 
     { 
   | 
||
| 
     	VALUE mon_count; 
   | 
||
| 
     	VALUE mon_mutex; 
   | 
||
| 
     	ID mon_count_id; 
   | 
||
| 
     	mon_count = rb_ivar_get(monitor, mon_count_id = rb_intern("@mon_count")); 
   | 
||
| 
     	rb_ivar_set(monitor, mon_count_id, mon_count = INT2NUM(NUM2INT(mon_count) - 1)); 
   | 
||
| 
     	if(mon_count == INT2NUM(0)) 
   | 
||
| 
     	{ 
   | 
||
| 
     		rb_ivar_set(monitor, rb_intern("@mon_owner"), Qnil); 
   | 
||
| 
     		mon_mutex = rb_ivar_get(monitor, rb_intern("@mon_mutex")); 
   | 
||
| 
     		rb_mutex_unlock(mon_mutex); 
   | 
||
| 
     	} 
   | 
||
| 
     	return mon_count; 
   | 
||
| 
     } 
   | 
||
| 
     VALUE 
   | 
||
| 
     rb_mon_exit(VALUE monitor) 
   | 
||
| 
     { 
   | 
||
| 
     	rb_mon_check_owner(monitor); 
   | 
||
| 
     	return rb_mon_exit_no_check(monitor); 
   | 
||
| 
     } 
   | 
||
| 
     VALUE 
   | 
||
| 
     mon_synchronize(VALUE monitor, VALUE (*func)(VALUE arg), VALUE arg) 
   | 
||
| 
     { 
   | 
||
| 
         rb_mon_enter(monitor); 
   | 
||
| 
         return rb_ensure(func, arg, rb_mon_exit_no_check, monitor); 
   | 
||
| 
     } 
   | 
||
| 
     VALUE 
   | 
||
| 
     rb_mon_synchronize(VALUE monitor) 
   | 
||
| 
     { 
   | 
||
| 
     	return mon_synchronize(monitor, rb_yield, Qnil); 
   | 
||
| 
     } 
   | 
||
| 
     void 
   | 
||
| 
     Init_monitor_mixin() 
   | 
||
| 
     { 
   | 
||
| 
     	rb_mMonitorMixin = rb_define_module("MonitorMixin"); 
   | 
||
| 
         rb_define_method(rb_mMonitorMixin, "mon_check_owner", rb_mon_check_owner, 0); 
   | 
||
| 
         rb_define_method(rb_mMonitorMixin, "mon_enter", rb_mon_enter, 0); 
   | 
||
| 
         rb_define_method(rb_mMonitorMixin, "mon_exit", rb_mon_exit, 0); 
   | 
||
| 
         rb_define_method(rb_mMonitorMixin, "mon_synchronize", rb_mon_synchronize, 0); 
   | 
||
| 
     } 
   | 
||
| lib/monitor.rb | ||
|---|---|---|
| 
     =end 
   | 
||
| 
     require 'thread' 
   | 
||
| 
     require 'monitor_mixin.so' 
   | 
||
| 
     # 
   | 
||
| 
     # Adds monitor functionality to an arbitrary object by mixing the module with 
   | 
||
| ... | ... | |
| 
       # For backward compatibility 
   | 
||
| 
       alias try_mon_enter mon_try_enter 
   | 
||
| 
       # 
   | 
||
| 
       # Enters exclusive section. 
   | 
||
| 
       # 
   | 
||
| 
       def mon_enter 
   | 
||
| 
         if @mon_owner != Thread.current 
   | 
||
| 
           @mon_mutex.lock 
   | 
||
| 
           @mon_owner = Thread.current 
   | 
||
| 
         end 
   | 
||
| 
         @mon_count += 1 
   | 
||
| 
       end 
   | 
||
| 
       # 
   | 
||
| 
       # Leaves exclusive section. 
   | 
||
| 
       # 
   | 
||
| 
       def mon_exit 
   | 
||
| 
         mon_check_owner 
   | 
||
| 
         @mon_count -=1 
   | 
||
| 
         if @mon_count == 0 
   | 
||
| 
           @mon_owner = nil 
   | 
||
| 
           @mon_mutex.unlock 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       # 
   | 
||
| 
       # Enters exclusive section and executes the block.  Leaves the exclusive 
   | 
||
| 
       # section automatically when the block exits.  See example under 
   | 
||
| 
       # +MonitorMixin+. 
   | 
||
| 
       # 
   | 
||
| 
       def mon_synchronize 
   | 
||
| 
         mon_enter 
   | 
||
| 
         begin 
   | 
||
| 
           yield 
   | 
||
| 
         ensure 
   | 
||
| 
           mon_exit 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       alias synchronize mon_synchronize 
   | 
||
| 
       # 
   | 
||
| ... | ... | |
| 
         @mon_mutex = Mutex.new 
   | 
||
| 
       end 
   | 
||
| 
       def mon_check_owner 
   | 
||
| 
         if @mon_owner != Thread.current 
   | 
||
| 
           raise ThreadError, "current thread not owner" 
   | 
||
| 
         end 
   | 
||
| 
       end 
   | 
||
| 
       def mon_enter_for_cond(count) 
   | 
||
| 
         @mon_owner = Thread.current 
   | 
||
| 
         @mon_count = count 
   | 
||
- « Previous
 - 1
 - 2
 - 3
 - 4
 - Next »