Revision: 3364 http://trac.macosforge.org/projects/ruby/changeset/3364 Author: ernest.prabhakar@gmail.com Date: 2010-01-29 15:40:04 -0800 (Fri, 29 Jan 2010) Log Message: ----------- Redid Dispatch actor and enumerable Modified Paths: -------------- MacRuby/trunk/lib/dispatch/actor.rb MacRuby/trunk/lib/dispatch/dispatch.rb MacRuby/trunk/lib/dispatch/enumerable.rb Modified: MacRuby/trunk/lib/dispatch/actor.rb =================================================================== --- MacRuby/trunk/lib/dispatch/actor.rb 2010-01-29 23:40:02 UTC (rev 3363) +++ MacRuby/trunk/lib/dispatch/actor.rb 2010-01-29 23:40:04 UTC (rev 3364) @@ -4,6 +4,10 @@ # and optinally calls back asynchronously (if given a block or group). # Note that this will NOT work for methods that themselves expect a block class Actor + + instance_methods.each |method| + undef_method(method) unless method =~ /__(.+)__|method_missing/ + end # Create an Actor to wrap the given +actee+, # optionally specifying the default +callback+ queue @@ -11,10 +15,10 @@ @actee = actee @callback_default = callback || Dispatch::Queue.concurrent @q = Dispatch::Queue.new("dispatch.actor.#{actee}.#{object_id}") - __reset! + __reset!__ end - def __reset! + def __reset!__ @callback = @callback_default @group = nil end @@ -28,6 +32,13 @@ def _with(group) @group = group end + + # Wait until the internal private queue has completed execution + # then returns the +actee+ delegate object + def _done + @q.sync { } + @actee + end def method_missing(symbol, *args, &block) if block_given? || not group.nil? @@ -36,7 +47,7 @@ retval = @actee.__send__(symbol, *args) callback.async { block.call(retval) } if not callback.nil? end - return __reset! + return __reset!__ else @retval = nil @q.sync { @retval = @actee.__send__(symbol, *args) } Modified: MacRuby/trunk/lib/dispatch/dispatch.rb =================================================================== --- MacRuby/trunk/lib/dispatch/dispatch.rb 2010-01-29 23:40:02 UTC (rev 3363) +++ MacRuby/trunk/lib/dispatch/dispatch.rb 2010-01-29 23:40:04 UTC (rev 3364) @@ -2,6 +2,13 @@ # directly from the top-level Dispatch module module Dispatch + # Returns a new serial queue with a unique label based on + # the ancestor chain and ID of +obj+ + def queue_for(obj) + label = obj.class.ancestors.reverse.join(".").downcase + Dispatch::Queue.new("#{label}.%x" % obj.object_id) + end + # Run the +&block+ asynchronously on a concurrent queue # of the given (optional) +priority+ def async(priority=nil, &block) Modified: MacRuby/trunk/lib/dispatch/enumerable.rb =================================================================== --- MacRuby/trunk/lib/dispatch/enumerable.rb 2010-01-29 23:40:02 UTC (rev 3363) +++ MacRuby/trunk/lib/dispatch/enumerable.rb 2010-01-29 23:40:04 UTC (rev 3364) @@ -20,11 +20,14 @@ grp.wait end - # Parallel +inject+ (only works if commutative) - def p_inject(initial=0, &block) + # Parallel +inject+ + # Requires initial value since 'first' no longer special. + # Only works if result doesn't depend on the order elements are processed. + def p_inject(initial, &block) @result = Dispatch.wrap(initial) self.p_each { |obj| block.call(@result, obj) } - @result + @result._done + return @result end # Parallel +collect+ @@ -36,19 +39,25 @@ result end - # Parallel +detect+ + # Parallel +select+; will return array of objects for which + # +&block+ returns true. + # Useful if the test block is very expensive to run + 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? + end + + # Parallel +detect+; will return -one- match for +&block+ + # but it may not be the 'first' + # Useful if the test block is very expensive to run def p_find(&block) - @done = false - @result = nil - self.p_each_with_index do |obj, i| - if not @done - if true == block.call(obj) - @done = true - @result = obj - end - end + @found = Dispatch.wrap(nil) + self.p_each do |obj| + found? = @found.nil? ? block.call(obj) : nil + @found = obj if found? and @found.nil? end - @result + @found._done # will this leak? end end end