Revision: 3455 http://trac.macosforge.org/projects/ruby/changeset/3455 Author: ernest.prabhakar@gmail.com Date: 2010-02-08 15:05:40 -0800 (Mon, 08 Feb 2010) Log Message: ----------- Create and pass spec for Enumerable#p_find Modified Paths: -------------- MacRuby/trunk/lib/dispatch/enumerable.rb MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb Modified: MacRuby/trunk/lib/dispatch/enumerable.rb =================================================================== --- MacRuby/trunk/lib/dispatch/enumerable.rb 2010-02-08 23:05:29 UTC (rev 3454) +++ MacRuby/trunk/lib/dispatch/enumerable.rb 2010-02-08 23:05:40 UTC (rev 3455) @@ -31,41 +31,50 @@ # Parallel +collect+ plus +inject+ # Accumulates from +initial+ via +op+ (default = '+') + # Note: each object can only run one mapreduce at a time def p_mapreduce(initial, op=:+, &block) + raise ArgumentError if not initial.respond_to? op + # Since exceptions from a Dispatch block can act funky @mapreduce_q ||= Dispatch::Queue.new("enumerable.p_mapreduce.#{object_id}") - # Ideally should set from within a Dispatch.once to avoid race - raise ArgumentError if not initial.respond_to? op - # Since exceptions from a Dispatch block act funky + # Ideally should run from within a Dispatch.once to avoid race @mapreduce_q.sync do - @result = initial - q = Dispatch.queue_for(@result) - p_each do |obj| + @mapreduce_result = initial + q = Dispatch.queue_for(@mapreduce_result) + self.p_each do |obj| val = block.call(obj) - q.async { @result = @result.send(op, val) } + q.async { @mapreduce_result = @mapreduce_result.send(op, val) } end q.sync {} - return @result # can return from inside the block + return @mapreduce_result end end - # Parallel +select+; will return array of objects for which # +&block+ returns true. def p_find_all(&block) found_all = Dispatch.wrap(Array) self.p_each { |obj| found_all << obj if block.call(obj) } - found_all._done # will this leak? + found_all._done_ end # Parallel +detect+; will return -one- match for +&block+ # but it may not be the 'first' # Only useful if the test block is very expensive to run + # Note: each object can only run one find at a time + def p_find(&block) - found = Dispatch.wrap(nil) - self.p_each do |obj| - found = found.nil? ? block.call(obj) : nil - found = obj if found and found.nil? + @find_q ||= Dispatch::Queue.new("enumerable.p_find.#{object_id}") + @find_q.sync do + @find_result = nil + q = Dispatch.queue_for(@find_result) + self.p_each do |obj| + if @find_result.nil? + found = block.call(obj) + q.async { @find_result = obj if found } + end + end + q.sync {} #if @find_result.nil? + return @find_result end - found._done # will this leak? end end Modified: MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb =================================================================== --- MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb 2010-02-08 23:05:29 UTC (rev 3454) +++ MacRuby/trunk/spec/macruby/library/dispatch/enumerable_spec.rb 2010-02-08 23:05:40 UTC (rev 3455) @@ -39,25 +39,18 @@ @ary.p_each_with_index {|v, i| temp = v**i; @q.sync {@sum2 += temp} } @sum2.should == @sum1 end - - it "should execute concurrently" do - true.should == true - end end describe :p_map do it "exists on objects that support Enumerable" do @ary.respond_to?(:p_map).should == true end + it "should behave like map" do map1 = @ary.map {|v| v*v} map2 = @ary.p_map {|v| v*v} map2.should == map1 end - - it "should execute concurrently" do - true.should == true - end end describe :p_mapreduce do @@ -85,11 +78,37 @@ sum2 = @ary.p_mapreduce(0, :|) {|v| v**2} sum2.should == sum1 end - - it "should execute concurrently" do - true.should == true + end + + describe :p_find_all do + it "exists on objects that support Enumerable" do + @ary.respond_to?(:p_find_all).should == true + end + + it "should behave like find_all" do + found1 = @ary.find_all {|v| v.odd?} + found2 = @ary.p_find_all {|v| v.odd?} + found2.sort.should == found1 end end + describe :p_find do + it "exists on objects that support Enumerable" do + @ary.respond_to?(:p_find).should == true + end + + it "returns nil if nothing found" do + found2 = @ary.p_find {|v| false} + found2.should.nil? + end + + it "returns one element that matches the condition" do + found1 = @ary.find_all {|v| v.odd?} + found2 = @ary.p_find {|v| v.odd?} + found2.should_not.nil? + found1.include? found2 + end + end + end end \ No newline at end of file
participants (1)
-
source_changes@macosforge.org