Revision: 3165 http://trac.macosforge.org/projects/ruby/changeset/3165 Author: ernest.prabhakar@gmail.com Date: 2009-12-23 13:33:07 -0800 (Wed, 23 Dec 2009) Log Message: ----------- Added finalizers for Dispatch classes Modified Paths: -------------- MacRuby/trunk/gcd.c MacRuby/trunk/spec/macruby/core/gcd/source_spec.rb MacRuby/trunk/spec/macruby/core/gcd/source_spec_disabled.rb MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/source_tags.txt Modified: MacRuby/trunk/gcd.c =================================================================== --- MacRuby/trunk/gcd.c 2009-12-23 21:04:48 UTC (rev 3164) +++ MacRuby/trunk/gcd.c 2009-12-23 21:33:07 UTC (rev 3165) @@ -77,9 +77,9 @@ struct RBasic basic; int suspension_count; dispatch_source_t source; - dispatch_source_type_t type; + dispatch_source_type_t type; // remove? rb_vm_block_t *event_handler; - rb_vm_block_t *cancel_handler; + rb_vm_block_t *cancel_handler;// remove? } rb_source_t; #define RSource(val) ((rb_source_t*)val) @@ -662,7 +662,21 @@ == 0 ? Qtrue : Qfalse; } +static IMP rb_group_finalize_super; +static void +rb_group_finalize(void *rcv, SEL sel) +{ + rb_group_t *grp = RGroup(rcv); + if (grp->group != NULL) { + dispatch_release(grp->group); + } + if (rb_group_finalize_super != NULL) { + ((void(*)(void *, SEL))rb_group_finalize_super)(rcv, sel); + } +} + + enum SOURCE_TYPE_ENUM { SOURCE_TYPE_DATA_ADD, @@ -716,22 +730,6 @@ return (NUM2LONG(num) == SOURCE_TYPE_TIMER) ? YES : NO; } - -static VALUE rb_source_on_event(VALUE self, SEL sel); -//static void rb_source_event_handler(void* sourceptr); - -static void -rb_source_close_file(void *source) -{ - assert(source != NULL); - uintptr_t handle = dispatch_source_get_handle(RSource(source)->source); - int filedes = (int)handle; - if (close(filedes) != 0) { - rb_raise(rb_eIOError, "Closing descriptor `%d' fails with error: %d", - filedes, errno); - } -} - static VALUE rb_source_alloc(VALUE klass, SEL sel) { @@ -741,6 +739,8 @@ return (VALUE)source; } +static VALUE rb_source_on_event(VALUE self, SEL sel); +static void rb_source_event_handler(void* sourceptr); static VALUE rb_source_init(VALUE self, SEL sel, @@ -753,16 +753,12 @@ NUM2UINT(handle), NUM2LONG(mask), RQueue(queue)->queue); if (rb_block_given_p()) { + fprintf(stderr, "Setting event handler for %p\n", (void*) src); rb_source_on_event(self, 0); } else { rb_raise(rb_eArgError, "No event handler for Dispatch::Source."); } - if (rb_is_file_source_type(type)) { - dispatch_set_context(src->source, (void*)self); // retain this? - dispatch_source_set_cancel_handler_f(src->source, rb_source_close_file); - } - rb_dispatch_resume(self, 0); // Does this work okay for timers? return self; } @@ -810,12 +806,22 @@ rb_source_t *src = RSource(self); rb_vm_block_t *block = given_block(); GC_WB(&src->event_handler, block); + fprintf(stderr, "Setting context for %p to %p\n", (void*) src->source, (void*) self); + GC_RETAIN(self); dispatch_set_context(src->source, (void *)self); // retain this? + fprintf(stderr, "Set context for %p\n", src); dispatch_source_set_event_handler_f(src->source, rb_source_event_handler); return Qnil; } static VALUE +rb_source_merge(VALUE self, SEL sel, VALUE data) +{ + dispatch_source_merge_data(RSource(self)->source, NUM2INT(data)); + return Qnil; +} + +static VALUE rb_source_cancel(VALUE self, SEL sel) { dispatch_source_cancel(RSource(self)->source); @@ -828,6 +834,25 @@ return dispatch_source_testcancel(RSource(self)->source) ? Qtrue : Qfalse; } +static IMP rb_source_finalize_super; + +static void +rb_source_finalize(void *rcv, SEL sel) +{ + rb_source_t *src = RSource(rcv); + if (src->source != NULL) { + while (src->suspension_count < 0) { + dispatch_resume(src->source); + src->suspension_count--; + } + dispatch_release(src->source); + } + if (rb_source_finalize_super != NULL) { + ((void(*)(void *, SEL))rb_source_finalize_super)(rcv, sel); + } + +} + static VALUE rb_semaphore_alloc(VALUE klass, SEL sel) { @@ -965,6 +990,10 @@ rb_objc_define_method(cGroup, "notify", rb_group_notify, 1); rb_objc_define_method(cGroup, "on_completion", rb_group_notify, 1); rb_objc_define_method(cGroup, "wait", rb_group_wait, -1); + + rb_group_finalize_super = rb_objc_install_method2((Class)cGroup, + "finalize", (IMP)rb_group_finalize); + cSource = rb_define_class_under(mDispatch, "Source", rb_cObject); rb_define_const(cSource, "DATA_ADD", INT2NUM(SOURCE_TYPE_DATA_ADD)); @@ -981,17 +1010,21 @@ rb_objc_define_method(cSource, "resume!", rb_dispatch_resume, 0); rb_objc_define_method(cSource, "suspend!", rb_dispatch_suspend, 0); rb_objc_define_method(cSource, "suspended?", rb_dispatch_suspended_p, 0); + rb_objc_define_method(cSource, "merge", rb_source_merge, 1); cTimer = rb_define_class_under(mDispatch, "Timer", cSource); rb_objc_define_method(cTimer, "initialize", rb_timer_init, -1); + rb_source_finalize_super = rb_objc_install_method2((Class)cSource, + "finalize", (IMP)rb_source_finalize); + cSemaphore = rb_define_class_under(mDispatch, "Semaphore", rb_cObject); rb_objc_define_method(*(VALUE *)cSemaphore, "alloc", rb_semaphore_alloc, 0); rb_objc_define_method(cSemaphore, "initialize", rb_semaphore_init, 1); rb_objc_define_method(cSemaphore, "wait", rb_semaphore_wait, -1); rb_objc_define_method(cSemaphore, "signal", rb_semaphore_signal, 0); - rb_queue_finalize_super = rb_objc_install_method2((Class)cSemaphore, + rb_semaphore_finalize_super = rb_objc_install_method2((Class)cSemaphore, "finalize", (IMP)rb_semaphore_finalize); rb_define_const(mDispatch, "TIME_NOW", ULL2NUM(DISPATCH_TIME_NOW)); Modified: MacRuby/trunk/spec/macruby/core/gcd/source_spec.rb =================================================================== --- MacRuby/trunk/spec/macruby/core/gcd/source_spec.rb 2009-12-23 21:04:48 UTC (rev 3164) +++ MacRuby/trunk/spec/macruby/core/gcd/source_spec.rb 2009-12-23 21:33:07 UTC (rev 3165) @@ -31,5 +31,12 @@ end end + describe "of type" do + before :each do + @q = Dispatch::Queue.new('org.macruby.gcd_spec.sources') + end + + end + end end Modified: MacRuby/trunk/spec/macruby/core/gcd/source_spec_disabled.rb =================================================================== --- MacRuby/trunk/spec/macruby/core/gcd/source_spec_disabled.rb 2009-12-23 21:04:48 UTC (rev 3164) +++ MacRuby/trunk/spec/macruby/core/gcd/source_spec_disabled.rb 2009-12-23 21:33:07 UTC (rev 3165) @@ -313,3 +313,63 @@ end end + +describe :DATA_ADD do + before :each do + @type = Dispatch::Source::DATA_ADD + end + + it "returns an instance of Dispatch::Source" do + p @type + src = Dispatch::Source.new(@type, 1, 2, @q) { true.should == true } + p src + src.should be_kind_of(Dispatch::Source) + end + + it "should not be suspended" do + src = Dispatch::Source.new(@type, 1, 2, @q) { true.should == true } + src.suspended?.should == false + end + + it "requires an event handler block" do + lambda { Dispatch::Source.new(@type, 1, 2, @q) }.should + raise_error(ArgumentError) + end + + it "fires event handler on merge" do + src = Dispatch::Source.new(@type, 1, 2, @q) do + true.should == true + end + lambda { src.merge 1 }.should_not raise_error(Exception) + @q.sync {} + end + + it "fires event handler on merge" do + src = Dispatch::Source.new(@type, 1, 2, @q) do + true.should == true + end + #src.merge 1 + @q.sync {} + end + + it "passes source to event handler" do + src = Dispatch::Source.new(@type, 1, 2, @q) do |source| + source.should be_kind_of(Dispatch::Source) + end + #src.merge 1 + @q.sync {} + end + + it "should execute event handler when Fixnum merged with <<" do + @src.suspend + @src.merge 20 + @src.merge 22 + @src.resume + @q.sync {} + end + + it "will only merge Fixnum arguments" do + lambda { @src.merge :foo}.should raise_error(ArgumentError) + end +end + Modified: MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/source_tags.txt =================================================================== --- MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/source_tags.txt 2009-12-23 21:04:48 UTC (rev 3164) +++ MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/source_tags.txt 2009-12-23 21:33:07 UTC (rev 3165) @@ -1,6 +0,0 @@ -fails:Dispatch::Source event handler will be invoked -fails:Dispatch::Source event handler receives the source -fails:Dispatch::Source event handler can get data -fails:Dispatch::Source event handler will get merged data -fails:Dispatch::Source event handler can get handle -fails:Dispatch::Source event handler can get mask
participants (1)
-
source_changes@macosforge.org