Revision: 3113 http://trac.macosforge.org/projects/ruby/changeset/3113 Author: ernest.prabhakar@gmail.com Date: 2009-12-14 16:26:43 -0800 (Mon, 14 Dec 2009) Log Message: ----------- Reverted gcd; cleaned up queue specs Modified Paths: -------------- MacRuby/trunk/gcd.c MacRuby/trunk/spec/macruby/core/gcd/queue_spec.rb MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/queue_tags.txt Modified: MacRuby/trunk/gcd.c =================================================================== --- MacRuby/trunk/gcd.c 2009-12-14 23:32:25 UTC (rev 3112) +++ MacRuby/trunk/gcd.c 2009-12-15 00:26:43 UTC (rev 3113) @@ -134,36 +134,16 @@ } } -#define SEC2NSEC_UINT64(sec) (uint64_t)((sec) * NSEC_PER_SEC) -#define SEC2NSEC_INT64(sec) (int64_t)((sec) * NSEC_PER_SEC) -#define TIMEOUT_MAX (1.0 * INT64_MAX / NSEC_PER_SEC) - static inline uint64_t -rb_num2nsec(VALUE num) +number_to_nanoseconds(VALUE num) { const double sec = rb_num2dbl(num); - fprintf(stderr, "rb_num2nsec: %lf/%lf\n", sec, TIMEOUT_MAX); if (sec < 0.0) { rb_raise(rb_eArgError, "negative delay specified"); } - return SEC2NSEC_UINT64(sec); + return (uint64_t)(((uint64_t)sec) * NSEC_PER_SEC); } -static inline dispatch_time_t -rb_num2timeout(VALUE num) -{ - dispatch_time_t dispatch_timeout = DISPATCH_TIME_FOREVER; - if (!NIL_P(num)) { - const double sec = rb_num2dbl(num); - if (sec < TIMEOUT_MAX) { - fprintf(stderr, "rb_num2timeout< %lf\n", sec); - dispatch_timeout = dispatch_walltime(NULL, SEC2NSEC_INT64(sec)); - } - } - fprintf(stderr, "rb_num2timeout> %llu\n", dispatch_timeout); - return dispatch_timeout; -} - static VALUE rb_queue_alloc(VALUE klass, SEL sel) { @@ -434,10 +414,15 @@ * gcdq.after(0.5) { puts 'wait is over :)' } * */ +// TODO: there is a max value that can be passed (int64_max / NSEC_PER_SEC); +// adjust for this. static VALUE rb_queue_dispatch_after(VALUE self, SEL sel, VALUE sec) { - dispatch_time_t offset = rb_num2timeout(sec); + sec = rb_Float(sec); + dispatch_time_t offset = dispatch_walltime(NULL, + (int64_t)(RFLOAT_VALUE(sec) * NSEC_PER_SEC)); + rb_vm_block_t *block = given_block(); block = rb_dispatch_prepare_block(block); @@ -656,10 +641,17 @@ static VALUE rb_group_wait(VALUE self, SEL sel, int argc, VALUE *argv) { - VALUE num; - rb_scan_args(argc, argv, "01", &num); - return dispatch_group_wait(RGroup(self)->group, rb_num2timeout(num)) - == 0 ? Qtrue : Qfalse; + dispatch_time_t timeout = DISPATCH_TIME_FOREVER; + VALUE float_timeout; + rb_scan_args(argc, argv, "01", &float_timeout); + if (!NIL_P(float_timeout)) { + // TODO: watch out for overflow here, too + double d = NUM2DBL(float_timeout); + int64_t to = (int64_t)(d * NSEC_PER_SEC); + timeout = dispatch_walltime(NULL, to); + } + return dispatch_group_wait(RGroup(self)->group, timeout) == 0 + ? Qtrue : Qfalse; } static VALUE rb_source_on_event(VALUE self, SEL sel); @@ -743,10 +735,10 @@ start_time = DISPATCH_TIME_NOW; } else { - start_time = rb_num2timeout(delay); + start_time = dispatch_walltime(NULL, number_to_nanoseconds(delay)); } - const uint64_t dispatch_interval = rb_num2nsec(interval); - const uint64_t dispatch_leeway = rb_num2nsec(leeway); + const uint64_t dispatch_interval = number_to_nanoseconds(interval); + const uint64_t dispatch_leeway = number_to_nanoseconds(leeway); VALUE src = rb_source_alloc(klass, sel); RSource(src)->source = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, @@ -852,19 +844,16 @@ } static VALUE -rb_semaphore_wait(VALUE self, SEL sel, int argc, VALUE *argv) +rb_semaphore_wait(VALUE self, SEL sel, VALUE time) { - VALUE num; - rb_scan_args(argc, argv, "01", &num); - return dispatch_semaphore_wait(RSemaphore(self)->sem, rb_num2timeout(num)) - == 0 ? Qtrue : Qfalse; + return LONG2NUM(dispatch_semaphore_wait(RSemaphore(self)->sem, + NUM2LL(time))); } static VALUE rb_semaphore_signal(VALUE self, SEL sel) { - return dispatch_semaphore_signal(RSemaphore(self)->sem) - == 0 ? Qtrue : Qfalse; + return LONG2NUM(dispatch_semaphore_signal(RSemaphore(self)->sem)); } static IMP rb_semaphore_finalize_super; @@ -982,7 +971,7 @@ 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, "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, Modified: MacRuby/trunk/spec/macruby/core/gcd/queue_spec.rb =================================================================== --- MacRuby/trunk/spec/macruby/core/gcd/queue_spec.rb 2009-12-14 23:32:25 UTC (rev 3112) +++ MacRuby/trunk/spec/macruby/core/gcd/queue_spec.rb 2009-12-15 00:26:43 UTC (rev 3113) @@ -3,185 +3,168 @@ #TODO: Dispatch::Queue.main.run (without killing spec runner!) if MACOSX_VERSION >= 10.6 - describe "Dispatch::Queue.concurrent" do - it "returns an instance of Queue" do - o = Dispatch::Queue.concurrent - o.should be_kind_of(Dispatch::Queue) + describe "Dispatch::Queue" do + before :each do + @q = Dispatch::Queue.new('org.macruby.gcd_spec.queue') end - it "can accept a symbol argument which represents the priority" do - o = Dispatch::Queue.concurrent(:low) - o.should be_kind_of(Dispatch::Queue) - - o = Dispatch::Queue.concurrent(:default) - o.should be_kind_of(Dispatch::Queue) + describe :concurrent do + it "returns an instance of Queue" do + q = Dispatch::Queue.concurrent + q.should be_kind_of(Dispatch::Queue) + end - o = Dispatch::Queue.concurrent(:high) - o.should be_kind_of(Dispatch::Queue) - end + it "can accept a symbol argument which represents the priority" do + q1 = Dispatch::Queue.concurrent(:low) + q1.should be_kind_of(Dispatch::Queue) - it "raises an ArgumentError if the given argument is not a valid priority symbol" do - lambda { Dispatch::Queue.concurrent(:foo) }.should raise_error(ArgumentError) - end - - it "should return the same queue object across invocations" do - a = Dispatch::Queue.concurrent(:low) - b = Dispatch::Queue.concurrent(:low) - a.should eql?(b) - end - - it "raises a TypeError if the provided priority is not a symbol" do - lambda { Dispatch::Queue.concurrent(42) }.should raise_error(TypeError) - end - end + q2 = Dispatch::Queue.concurrent(:default) + q2.should be_kind_of(Dispatch::Queue) - describe "Dispatch::Queue.current" do - it "returns an instance of Queue" do - o = Dispatch::Queue.current - o.should be_kind_of(Dispatch::Queue) - end - - it "should return the parent queue when inside an executing block" do - q = Dispatch::Queue.new('org.macruby.gcd_spec.queue') - @q2 = nil - q.async do - @q2 = Dispatch::Queue.current + q3 = Dispatch::Queue.concurrent(:high) + q3.should be_kind_of(Dispatch::Queue) end - q.sync {} - q.label.should == @q2.label - end - end - describe "Dispatch::Queue.main" do - it "returns an instance of Queue" do - o = Dispatch::Queue.main - o.should be_kind_of(Dispatch::Queue) + it "raises an ArgumentError if the argument is not a valid priority" do + lambda { Dispatch::Queue.concurrent(:foo) }.should raise_error(ArgumentError) + end + + it "should return the same queue object across invocations" do + qa = Dispatch::Queue.concurrent(:low) + qb = Dispatch::Queue.concurrent(:low) + qa.should eql?(qb) + end + + it "raises a TypeError if the provided priority is not a symbol" do + lambda { Dispatch::Queue.concurrent(42) }.should raise_error(TypeError) + end end - end - describe "Dispatch::Queue.new" do - it "accepts a name and returns an instance of Queue" do - o = Dispatch::Queue.new('foo') - o.should be_kind_of(Dispatch::Queue) + describe :current do + it "returns an instance of Queue" do + @q.should be_kind_of(Dispatch::Queue) + end - lambda { Dispatch::Queue.new('foo', 42) }.should raise_error(ArgumentError) - lambda { Dispatch::Queue.new(42) }.should raise_error(TypeError) + it "should return the parent queue when inside an executing block" do + @q2 = nil + @q.async do + @q2 = Dispatch::Queue.current + end + @q.sync {} + @q.label.should == @q2.label + end end - - it "raises an ArgumentError if not passed a string" do - lambda { Dispatch::Queue.new() }.should raise_error(ArgumentError) - end - end - describe "Dispatch::Queue#async" do - it "accepts a block and yields it asynchronously" do - o = Dispatch::Queue.new('foo') - @i = 0 - o.async { @i = 42 } - while @i == 0 do; end - @i.should == 42 + describe :main do + it "returns an instance of Queue" do + o = Dispatch::Queue.main + @q.should be_kind_of(Dispatch::Queue) + end end + describe :new do + it "accepts a name and returns an instance of Queue" do + @q.should be_kind_of(Dispatch::Queue) - it "raises an ArgumentError if no block is given" do - o = Dispatch::Queue.new('foo') - lambda { o.async }.should raise_error(ArgumentError) - end - end + lambda { Dispatch::Queue.new('foo', 42) }.should raise_error(ArgumentError) + lambda { Dispatch::Queue.new(42) }.should raise_error(TypeError) + end - describe "Dispatch::Queue#sync" do - it "accepts a block and yields it synchronously" do - o = Dispatch::Queue.new('foo') - @i = 0 - o.sync { @i = 42 } - @i.should == 42 + it "raises an ArgumentError if not passed a string" do + lambda { Dispatch::Queue.new() }.should raise_error(ArgumentError) + end end - it "raises an ArgumentError if no block is given" do - o = Dispatch::Queue.new('foo') - lambda { o.sync }.should raise_error(ArgumentError) - end - end + describe :async do + it "accepts a block and yields it asynchronously" do + @i = 0 + @q.async { @i = 42 } + while @i == 0 do; end + @i.should == 42 + end - describe "Dispatch::Queue#apply" do - it "accepts an input size and a block and yields it as many times" do - o = Dispatch::Queue.new('foo') - @i = 0 - o.apply(10) { @i += 1 } - @i.should == 10 - @i = 42 - o.apply(0) { @i += 1 } - @i.should == 42 - lambda { o.apply(nil) {} }.should raise_error(TypeError) + it "raises an ArgumentError if no block is given" do + lambda { @q.async }.should raise_error(ArgumentError) + end end - it "raises an ArgumentError if no block is given" do - o = Dispatch::Queue.new('foo') - lambda { o.apply(42) }.should raise_error(ArgumentError) - end - end + describe :sync do + it "accepts a block and yields it synchronously" do + @i = 0 + @q.sync { @i = 42 } + @i.should == 42 + end - describe "Dispatch::Queue#after" do - it "accepts a given time (in seconds) and a block and yields it after" do - o = Dispatch::Queue.new('foo') - [1.0, 2, 0.9, 1.5].each do |test_time| - - t = Time.now - o.after(test_time) { @i = 42 } - @i = 0 - while @i == 0 do; end - @i.should == 42 - t2 = Time.now - t - t2.should > test_time - t2.should < test_time*2 + it "raises an ArgumentError if no block is given" do + lambda { @q.sync }.should raise_error(ArgumentError) end end - it "raises an ArgumentError if no time is given" do - o = Dispatch::Queue.new('foo') - lambda { o.after(nil) {} }.should raise_error(TypeError) - end + describe :apply do + it "accepts an input size and a block and yields it as many times" do + @i = 0 + @q.apply(10) { @i += 1 } + @i.should == 10 + @i = 42 + @q.apply(0) { @i += 1 } + @i.should == 42 - it "raises an ArgumentError if no block is given" do - o = Dispatch::Queue.new('foo') - lambda { o.after(42) }.should raise_error(ArgumentError) + lambda { @q.apply(nil) {} }.should raise_error(TypeError) + end + + it "raises an ArgumentError if no block is given" do + lambda { @q.apply(42) }.should raise_error(ArgumentError) + end end - end - describe "Dispatch::Queue#label" do - it "returns the name of the queue" do - o = Dispatch::Queue.new('foo') - o.label.should == 'foo' + describe :after do + it "accepts a given time (in seconds) and a block and yields it after" do + [0.1].each do |test_time| - o = Dispatch::Queue.main - o.label.should == 'com.apple.main-thread' - end + t = Time.now + @q.after(test_time) { @i = 42 } + @i = 0 + while @i == 0 do; end + @i.should == 42 + t2 = Time.now - t + t2.should > test_time + t2.should < test_time*2 + end + end - it "is also returned by to_s" do - o = Dispatch::Queue.new('foo') - o.to_s.should == o.label + it "raises an ArgumentError if no time is given" do + lambda { @q.after(nil) {} }.should raise_error(TypeError) + end - o = Dispatch::Queue.main - o.to_s.should == 'com.apple.main-thread' + it "raises an ArgumentError if no block is given" do + lambda { @q.after(42) }.should raise_error(ArgumentError) + end end - it "is included as part of inspect" do - o = Dispatch::Queue.new('foo') - o.inspect.index('foo').should.be_kind_of(Fixnum) + describe :label, :shared => true do + it "returns the name of the queue" do + @q.label.should == 'org.macruby.gcd_spec.queue' + + qm = Dispatch::Queue.main + qm.label.should == 'com.apple.main-thread' + end + end + + describe :to_s do + it_should_behave_like :label end - end - describe "Dispatch::Queue#suspend!" do - it "suspends the queue which can be resumed by calling #resume!" do - o = Dispatch::Queue.new('foo') - o.async { sleep 1 } - o.suspended?.should == false - o.suspend! - o.suspended?.should == true - o.resume! - o.suspended?.should == false + describe :suspend! do + it "suspends the queue which can be resumed by calling #resume!" do + @q.async { sleep 1 } + @q.suspended?.should == false + @q.suspend! + @q.suspended?.should == true + @q.resume! + @q.suspended?.should == false + end end + end - -end +end \ No newline at end of file Modified: MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/queue_tags.txt =================================================================== --- MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/queue_tags.txt 2009-12-14 23:32:25 UTC (rev 3112) +++ MacRuby/trunk/spec/macruby/tags/macruby/core/gcd/queue_tags.txt 2009-12-15 00:26:43 UTC (rev 3113) @@ -1,2 +1,2 @@ -critical:Dispatch::Queue.new raises an ArgumentError if not passed a string +critical:Dispatch::Queue new raises an ArgumentError if not passed a string
participants (1)
-
source_changes@macosforge.org