Revision: 4312 http://trac.macosforge.org/projects/ruby/changeset/4312 Author: ernest.prabhakar@gmail.com Date: 2010-06-30 14:03:49 -0700 (Wed, 30 Jun 2010) Log Message: ----------- Updated dispatch/README.rdoc and source to fix syntax errors from Ticket #745 Modified Paths: -------------- MacRuby/trunk/lib/dispatch/README.rdoc MacRuby/trunk/lib/dispatch/enumerable.rb MacRuby/trunk/lib/dispatch/source.rb MacRuby/trunk/sample-macruby/Scripts/gcd/dispatch_methods.rb MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb Modified: MacRuby/trunk/lib/dispatch/README.rdoc =================================================================== --- MacRuby/trunk/lib/dispatch/README.rdoc 2010-06-30 19:45:48 UTC (rev 4311) +++ MacRuby/trunk/lib/dispatch/README.rdoc 2010-06-30 21:03:49 UTC (rev 4312) @@ -84,7 +84,7 @@ Additionally, you can call +values+ to obtain all the values: @values = job.values - puts @values # => [1.0E50, 4294967296.0] + puts @values.inspect # => [1.0E50, 4294967296.0] Note that unlike +value+ this will not +wait+ or +join+, and thus does not have an asynchronous equivalent. @@ -100,11 +100,11 @@ The easiest way to create a Proxy is to first create an empty Job: - job = Dispatch::Job.new + job = Dispatch::Job.new {} then ask it to wrap the object you want to modify from multiple threads: - @hash = job.synchronize {} + @hash = job.synchronize Hash.new puts @hash.class # => Dispatch::Proxy This is actually the same type of object used to manage the list of +values+: @@ -121,7 +121,7 @@ Except that you can use it safely inside Dispatch blocks from multiple threads: [64, 100].each do |n| - job << { @hash[n] = Math.sqrt(10**n) } + job.add { @hash[n] = Math.sqrt(10**n) } end puts @hash.inspect # => {64 => 1.0E32, 100 => 1.0E50} @@ -200,9 +200,9 @@ Passes each object and its index, like +each_with_index+: - %w(Mon Tue Wed Thu Fri).p_each { |day, i | puts "#{i}:#{day}"} # => 0:Mon 2:Wed 3:Thu 1:Tue 4:Fri + %w(Mon Tue Wed Thu Fri).p_each_with_index { |day, i | puts "#{i}:#{day}"} # => 0:Mon 2:Wed 3:Thu 1:Tue 4:Fri - %w(Mon Tue Wed Thu Fri).p_each(3) { |day, i | puts "#{i}:#{day}"} # => 3:Thu 4:Fri 0:Mon 1:Tue 2:Wed + %w(Mon Tue Wed Thu Fri).p_each_with_index(3) { |day, i | puts "#{i}:#{day}"} # => 3:Thu 4:Fri 0:Mon 1:Tue 2:Wed === Enumerable#p_map @@ -218,7 +218,7 @@ (0..4).p_mapreduce(0) { |i| 10**i } # => 11111 -This uses a parallel +inject+ (formerly known as +reduce+) to return a single value by combining the result of +map+. Unlike +inject+, you must specify an explicit initial value as the first parameter. The default accumulator is ":+", but you can specify a different symbol to +send+: +This uses a parallel +inject+ (formerly known as +reduce+) to return a single value by combining the result of +map+. Unlike +inject+, you must specify an explicit initial value as the first parameter. The default accumulator is ":+", but you can specify a different symbol to +send+: (0..4).p_mapreduce([], :concat) { |i| [10**i] } # => [1, 1000, 10, 100, 10000] @@ -226,23 +226,23 @@ (0..4).p_mapreduce([], :concat, 3) { |i| [10**i] } # => [1000, 10000, 1, 10, 100] -=== Enumerable#p_findall +=== Enumerable#p_find_all Passes each object and collects those for which the block is true, like +findall+: - (0..4).p_findall { |i| i.odd?} # => {3, 1} + (0..4).p_find_all { |i| i.odd?} # => {3, 1} - (0..4).p_findall(3) { |i| i.odd?} # => {3, 1} + (0..4).p_find_all(3) { |i| i.odd?} # => {3, 1} === Enumerable#p_find Passes each object and returns nil if none match. Similar to +find+, it returns the first object it _finds_ for which the block is true, but unlike +find+ that may not be the _actual_ first object since blocks -- say it with me -- "may complete out of order": - (0..4).p_findall { |i| i == 5 } # => nil + (0..4).p_find_all { |i| i == 5 } # => nil - (0..4).p_findall { |i| i.odd?} # => 1 + (0..4).p_find_all { |i| i.odd?} # => 1 - (0..4).p_findall(3) { |i| i.odd?} # => 3 + (0..4).p_find_all(3) { |i| i.odd?} # => 3 == Sources: Asynchronous Events @@ -260,7 +260,7 @@ We'll start with a simple example: a +periodic+ timer that runs every 0.9 seconds and prints out the number of pending events: - timer = Source.periodic(0.9) { |src| puts src.data } + timer = Dispatch::Source.periodic(0.9) { |src| puts src.data } sleep 2 # => 1 1 ... If you're familiar with the C API for GCD, be aware that a +Dispatch::Source+ is fully configured at the time of instantiation, and does not need to be +resume+d. Also, times are in seconds, not nanoseconds. @@ -369,9 +369,9 @@ Alternatively, you can pass in array of names (symbols or strings) for the mask, and optionally use +data2events+ to convert the returned data into an array of symbols @events = [] - mask2 = [:exit, :fork, :exec, signal] + mask2 = [:exit, :fork, :exec, :signal] proc_src2 = Dispatch::Source.process($$, mask2) do |s| - |s| @events << Dispatch::Source.data2events(s.data) + @events << Dispatch::Source.data2events(s.data) end ==== Source.process Example @@ -405,7 +405,7 @@ Similarly, use +num2event+ to turn an int into a symbol: - put result2[0] == Dispatch::Source#num2event(result) # => true + puts result2[0] == Dispatch::Source#num2event(result) # => true ==== Source.signal @@ -447,14 +447,14 @@ @msg = "#{$$}-#{Time.now.to_s.gsub(' ','_')}" filename = "/tmp/dispatch-#{@msg}" file = File.open(filename, "w") - fmask = Dispatch::Source::VNODE_DELETE | Dispatch::Source::Source.VNODE_WRITE + fmask = Dispatch::Source::VNODE_DELETE | Dispatch::Source::VNODE_WRITE file_src = Dispatch::Source.file(file.fileno, fmask) do |s| @fevent |= s.data end file.puts @msg file.flush file.close - puts @fevent & fmask # => Dispatch::Source::Source.VNODE_WRITE + puts @fevent & fmask # => Dispatch::Source::VNODE_WRITE File.delete(filename) puts @fevent == fmask # => true file_src.cancel! @@ -481,7 +481,7 @@ file = File.open(filename, "r") @result = "" reader = Dispatch::Source.read(file) do |s| - @result << @file.read(s.data) + @result << @file.read(s.data) end while (@result.size < @msg.size) do; end puts @result # => e.g., 489-Wed_Mar_24_15:59:00_-0700_2010 @@ -496,11 +496,11 @@ file = File.open(filename, "w") @message = @msg writer = Dispatch::Source.write(file) do |s| - if @message.size > 0 then - char = @message[0..0] - @file.write(char) - @message = @message[1..-1] - end + if @message.size > 0 then + char = @message[0..0] + @file.write(char) + @message = @message[1..-1] + end end while (@message.size > 0) do; end result = File.read(filename) Modified: MacRuby/trunk/lib/dispatch/enumerable.rb =================================================================== --- MacRuby/trunk/lib/dispatch/enumerable.rb 2010-06-30 19:45:48 UTC (rev 4311) +++ MacRuby/trunk/lib/dispatch/enumerable.rb 2010-06-30 21:03:49 UTC (rev 4312) @@ -42,13 +42,13 @@ # Parallel +each+ def p_each(stride=1, priority=nil, &block) ary = self.to_a - size.p_times(stride, priority) { |i| block.call(ary[i]) } + ary.count.p_times(stride, priority) { |i| block.call(ary[i]) } end # Parallel +each+ def p_each_with_index(stride=1, priority=nil, &block) ary = self.to_a - size.p_times(stride, priority) { |i| block.call(ary[i], i) } + ary.count.p_times(stride, priority) { |i| block.call(ary[i], i) } end # Parallel +collect+ Modified: MacRuby/trunk/lib/dispatch/source.rb =================================================================== --- MacRuby/trunk/lib/dispatch/source.rb 2010-06-30 19:45:48 UTC (rev 4311) +++ MacRuby/trunk/lib/dispatch/source.rb 2010-06-30 21:03:49 UTC (rev 4312) @@ -70,8 +70,8 @@ # Takes events: :exit, :fork, :exec, :signal # Returns Dispatch::Source of type VNODE def file(file, events, queue = Dispatch::Queue.concurrent, &block) - mask = events2mask(events) - Dispatch::Source.new(Dispatch::Source::VNODE, file, mask, queue, &block) + events = events2mask(events) if not events.respond_to? :to_int + Dispatch::Source.new(Dispatch::Source::VNODE, file, events, queue, &block) end def periodic(seconds, queue = Dispatch::Queue.concurrent, &block) Modified: MacRuby/trunk/sample-macruby/Scripts/gcd/dispatch_methods.rb =================================================================== --- MacRuby/trunk/sample-macruby/Scripts/gcd/dispatch_methods.rb 2010-06-30 19:45:48 UTC (rev 4311) +++ MacRuby/trunk/sample-macruby/Scripts/gcd/dispatch_methods.rb 2010-06-30 21:03:49 UTC (rev 4312) @@ -1,20 +1,19 @@ -#!/usr/bin/env macruby - +#!/usr/local/bin/macruby require 'dispatch' job = Dispatch::Job.new { Math.sqrt(10**100) } @result = job.value -puts @result.to_int.to_s.size # => 51 +puts @result.to_int.to_s.size # => 50 -job.value {|v| p v.to_int.to_s.size } # => 51 (eventually) +job.value {|v| p v.to_int.to_s.size } # => 50 (eventually) job.join puts "All Done" job.join { puts "All Done" } job.add { Math.sqrt(2**64) } @values = job.values -puts @values # => [1.0E50, 4294967296.0] -job = Dispatch::Job.new -@hash = job.synchronize {} +puts @values.inspect # => [1.0E50, 4294967296.0] +job = Dispatch::Job.new {} +@hash = job.synchronize Hash.new puts @hash.class # => Dispatch::Proxy puts job.values.class # => Dispatch::Proxy @@ -24,7 +23,7 @@ [64, 100].each do |n| - job << { @hash[n] = Math.sqrt(10**n) } + job.add { @hash[n] = Math.sqrt(10**n) } end puts @hash.inspect # => {64 => 1.0E32, 100 => 1.0E50} @@ -49,29 +48,28 @@ 5.p_times(3) { |i| puts 10**i } # =>1000 10000 1 10 100 %w(Mon Tue Wed Thu Fri).p_each { |day| puts day} # => Mon Wed Thu Tue Fri %w(Mon Tue Wed Thu Fri).p_each(3) { |day| puts day} # => Thu Fri Mon Tue Wed -%w(Mon Tue Wed Thu Fri).p_each { |day, i | puts "#{i}:#{day}"} # => 0:Mon 2:Wed 3:Thu 1:Tue 4:Fri -%w(Mon Tue Wed Thu Fri).p_each(3) { |day, i | puts "#{i}:#{day}"} # => 3:Thu 4:Fri 0:Mon 1:Tue 2:Wed +%w(Mon Tue Wed Thu Fri).p_each_with_index { |day, i | puts "#{i}:#{day}"} # => 0:Mon 2:Wed 3:Thu 1:Tue 4:Fri +%w(Mon Tue Wed Thu Fri).p_each_with_index(3) { |day, i | puts "#{i}:#{day}"} # => 3:Thu 4:Fri 0:Mon 1:Tue 2:Wed (0..4).p_map { |i| 10**i } # => [1, 1000, 10, 100, 10000] (0..4).p_map(3) { |i| 10**i } # => [1000, 10000, 1, 10, 100] (0..4).p_mapreduce(0) { |i| 10**i } # => 11111 -This uses a parallel +inject+ (formerly known as +reduce+) to return a single value by combining the result of +map+. Unlike +inject+, you must specify an explicit initial value as the first parameter. The default accumulator is ":+", but you can specify a different symbol to +send+: (0..4).p_mapreduce([], :concat) { |i| [10**i] } # => [1, 1000, 10, 100, 10000] (0..4).p_mapreduce([], :concat, 3) { |i| [10**i] } # => [1000, 10000, 1, 10, 100] -(0..4).p_findall { |i| i.odd?} # => {3, 1} -(0..4).p_findall(3) { |i| i.odd?} # => {3, 1} +(0..4).p_find_all { |i| i.odd?} # => {3, 1} +(0..4).p_find_all(3) { |i| i.odd?} # => {3, 1} -(0..4).p_findall { |i| i == 5 } # => nil -(0..4).p_findall { |i| i.odd?} # => 1 -(0..4).p_findall(3) { |i| i.odd?} # => 3 +(0..4).p_find_all { |i| i == 5 } # => nil +(0..4).p_find_all { |i| i.odd?} # => 1 +(0..4).p_find_all(3) { |i| i.odd?} # => 3 -timer = Source.periodic(0.9) { |src| puts src.data } -sleep 2 # => 1 1 ... +timer = Dispatch::Source.periodic(0.9) { |src| puts src.data } +sleep 0.2 # => 1 1 ... timer.suspend! -sleep 2 +sleep 0.2 timer.resume! -sleep 2 # => 2 1 ... +sleep 0.2 # => 2 1 ... timer.cancel! @sum = 0 adder = Dispatch::Source.add { |s| @sum += s.data; } @@ -95,11 +93,10 @@ @event |= s.data end - @events = [] -mask2 = [:exit, :fork, :exec, signal] +mask2 = [:exit, :fork, :exec, :signal] proc_src2 = Dispatch::Source.process($$, mask2) do |s| - |s| @events << Dispatch::Source.data2events(s.data) + @events << Dispatch::Source.data2events(s.data) end sig_usr1 = Signal.list["USR1"] Signal.trap(sig_usr1, "IGNORE") @@ -110,11 +107,11 @@ result2 = (@events & mask2) # => [:signal] proc_src2.cancel! puts result == Dispatch::Source#event2num(result2[0]) # => true -put result2[0] == Dispatch::Source#num2event(result) # => true +puts result2[0] == Dispatch::Source#num2event(result) # => true @count = 0 sig_usr2 = Signal.list["USR2"] signal = Dispatch::Source.signal(sig_usr2) do |s| -@count += s.data + @count += s.data end signal.suspend! Signal.trap(sig_usr2, "IGNORE") @@ -125,13 +122,14 @@ signal.cancel! @fevent = 0 @msg = "#{$$}-#{Time.now.to_s.gsub(' ','_')}" +filename = "/tmp/dispatch-#{@msg}" file = File.open(filename, "w") -fmask = Dispatch::Source::VNODE_DELETE | Dispatch::Source::Source.VNODE_WRITE +fmask = Dispatch::Source::VNODE_DELETE | Dispatch::Source::VNODE_WRITE file_src = Dispatch::Source.file(file.fileno, fmask) do |s| -@fevent |= s.data + @fevent |= s.data end file.close -puts @fevent & fmask # => Dispatch::Source::Source.VNODE_WRITE +puts @fevent & fmask # => Dispatch::Source::VNODE_WRITE File.delete(filename) puts @fevent == fmask # => true file_src.cancel! @@ -140,11 +138,29 @@ file = File.open(filename, "w") fmask2 = %w(delete write) file_src2 = Dispatch::Source.file(file, fmask2) do |s| -@fevent2 << Dispatch::Source.data2events(s.data) + @fevent2 << Dispatch::Source.data2events(s.data) end puts @fevent2 & fmask2 # => [:write] file_src2.cancel! - @result << @file.read(s.data) +file = File.open(filename, "r") +@result = "" +reader = Dispatch::Source.read(file) do |s| + @result << @file.read(s.data) end +while (@result.size < @msg.size) do; end +puts @result # => e.g., 489-Wed_Mar_24_15:59:00_-0700_2010 reader.cancel! + +file = File.open(filename, "w") +@message = @msg +writer = Dispatch::Source.write(file) do |s| + if @message.size > 0 then + char = @message[0..0] + @file.write(char) + @message = @message[1..-1] + end +end +while (@message.size > 0) do; end +result = File.read(filename) +puts result # => e.g., 489-Wed_Mar_24_15:59:00_-0700_2010 Modified: MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb =================================================================== --- MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb 2010-06-30 19:45:48 UTC (rev 4311) +++ MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb 2010-06-30 21:03:49 UTC (rev 4312) @@ -57,12 +57,14 @@ describe "Enumerable" do before :each do - @ary = (1..3).to_a + @rng = (1..3) + @ary = @rng.to_a end describe :p_each do it "exists on objects that support Enumerable" do @ary.respond_to?(:p_each).should == true + @rng.respond_to?(:p_each).should == true end it "should behave like each" do @@ -74,6 +76,15 @@ @ary2.should == @ary1 end + it "should work with ranges" do + @ary1 = 0 + @ary.each {|v| @ary1 << v*v} + @ary2 = 0 + @q = Dispatch::Queue.for(@ary2) + @rng.p_each {|v| temp = v*v; @q.sync {@ary2 << temp} } + @ary2.should == @ary1 + end + it "should execute concurrently" do t0 = Time.now @ary.p_each {|v| sleep v/100.0}
participants (1)
-
source_changes@macosforge.org