[macruby-changes] [3336] MacRuby/trunk

source_changes at macosforge.org source_changes at macosforge.org
Mon Jan 25 16:39:08 PST 2010


Revision: 3336
          http://trac.macosforge.org/projects/ruby/changeset/3336
Author:   ernest.prabhakar at gmail.com
Date:     2010-01-25 16:39:08 -0800 (Mon, 25 Jan 2010)
Log Message:
-----------
Created Dispatch helper library for convenience methods

Added Paths:
-----------
    MacRuby/trunk/lib/dispatch/enumerable.rb
    MacRuby/trunk/lib/dispatch/queue.rb
    MacRuby/trunk/lib/dispatch.rb
    MacRuby/trunk/spec/macruby/library/
    MacRuby/trunk/spec/macruby/library/dispatch/
    MacRuby/trunk/spec/macruby/library/dispatch/queue_source_spec.rb
    MacRuby/trunk/spec/macruby/library/dispatch/queue_spec.rb
    MacRuby/trunk/spec/macruby/tags/macruby/library/
    MacRuby/trunk/spec/macruby/tags/macruby/library/dispatch/
    MacRuby/trunk/spec/macruby/tags/macruby/library/dispatch/queue_spec_tags.txt
    MacRuby/trunk/spec/macruby/tags/macruby/library/dispatch/queue_tags.txt

Removed Paths:
-------------
    MacRuby/trunk/spec/macruby/core/gcd/prelude_spec.rb

Added: MacRuby/trunk/lib/dispatch/enumerable.rb
===================================================================
--- MacRuby/trunk/lib/dispatch/enumerable.rb	                        (rev 0)
+++ MacRuby/trunk/lib/dispatch/enumerable.rb	2010-01-26 00:39:08 UTC (rev 3336)
@@ -0,0 +1,18 @@
+module Dispatch
+  module Enumerable
+    def p_map(&block)
+      result = []
+      # We will access the `result` array from within this serial queue,
+      # as without a GIL we cannot assume array access to be thread-safe.
+      result_queue = Dispatch::Queue.new('access-queue.#{result.object_id}')
+      # Uses Dispatch::Queue#apply to submit many blocks at once
+      Dispatch::Queue.concurrent.apply(size) do |idx|
+        # run the block in the concurrent queue to maximize parallelism
+        temp = block(self[idx])
+        # do only the assignment on the serial queue
+        result_queue.async { result[idx] = temp }
+      end
+      result
+    end
+  end
+end

Added: MacRuby/trunk/lib/dispatch/queue.rb
===================================================================
--- MacRuby/trunk/lib/dispatch/queue.rb	                        (rev 0)
+++ MacRuby/trunk/lib/dispatch/queue.rb	2010-01-26 00:39:08 UTC (rev 3336)
@@ -0,0 +1,16 @@
+module Dispatch
+  class Queue
+    # Combines +&block+ up to +stride+ times before passing to Queue::Apply
+    def stride(count, stride=1, &block)
+      sub_count = (count / stride).to_int
+      puts "\nsub_count: #{sub_count} (#{count} / #{stride})"
+      apply(sub_count) do |i|
+        i0 = i*stride
+        (i0..i0+stride).each { |j| "inner #{j}"; block.call(j) } #nested dispatch blocks fails
+      end
+      done = sub_count*stride;
+      puts "\ndone: #{done} (#{sub_count}*#{stride})"
+      (done..count).each { |j| p "inner #{j}"; block.call(j) }
+    end
+  end
+end

Added: MacRuby/trunk/lib/dispatch.rb
===================================================================
--- MacRuby/trunk/lib/dispatch.rb	                        (rev 0)
+++ MacRuby/trunk/lib/dispatch.rb	2010-01-26 00:39:08 UTC (rev 3336)
@@ -0,0 +1,19 @@
+# 
+# dispatch.rb - Grand Central Dispatch support library
+# 
+# Copyright (C) 2010  Apple, Inc.
+# 
+# == Overview
+#
+# Grand Central Dispatch (GCD) is a novel approach to multicore computing
+# first released in Mac OS X version 10.6 Snow Leopard.
+# The Dispatch module and associated classes (Queue, Group, Semaphore, Source)
+# in MacRuby core provides a simple wrapping on top of the libdispatch C API.
+# This library provides higher-level services and convenience methods
+# to make it easier for traditional Ruby programmers to add multicore support.
+
+raise "Dispatch will only work on Mac OS X 10.6 or later" if MACOSX_VERSION < 10.6
+
+require 'dispatch/queue'
+require 'dispatch/queue_source'
+require 'dispatch/enumerable'

Deleted: MacRuby/trunk/spec/macruby/core/gcd/prelude_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/core/gcd/prelude_spec.rb	2010-01-26 00:39:06 UTC (rev 3335)
+++ MacRuby/trunk/spec/macruby/core/gcd/prelude_spec.rb	2010-01-26 00:39:08 UTC (rev 3336)
@@ -1,146 +0,0 @@
-require File.dirname(__FILE__) + "/../../spec_helper"
-require File.dirname(__FILE__) + "/../../../../gcd_prelude"
-
-if MACOSX_VERSION >= 10.6
-
-  describe "Dispatch::Queue source from" do
-    before :each do
-      @q = Dispatch::Queue.new('org.macruby.gcd_spec.prelude')
-      @src = nil
-    end
-
-    after :each do
-      @src.cancel! if not @src.nil? and not @src.cancelled?
-      @q.sync { }
-    end
-
-    describe "on_add" do
-      it "fires with data on summed inputs" do
-        @count = 0
-        @src = @q.on_add {|s| @count += s.data}
-        @src << 20
-        @src << 22
-        @q.sync {}
-        @count.should == 42
-      end
-    end    
-
-    describe "on_or" do
-      it "fires with data on ORed inputs" do
-        @count = 0
-        @src = @q.on_or {|s| @count += s.data}
-        @src << 0b101_000
-        @src << 0b000_010
-        @q.sync {}
-        @count.should == 42
-      end
-    end    
-
-    describe "on_process_event" do
-      it "fires with data indicating which process event(s)" do
-        @signal = Signal.list["USR1"]
-        @event = nil
-        @src = @q.on_process_event($$, :exit, :fork, :exec, :signal) do 
-           |s| @event = s.data
-        end
-        Signal.trap(@signal, "IGNORE")
-        Process.kill(@signal, $$)
-        Signal.trap(@signal, "DEFAULT")
-        @q.sync {}
-        @event.should == Dispatch::Source.proc_event(:signal)
-      end
-    end
-
-    describe "on_signal" do
-      it "fires with data on how often the process was signaled" do
-        @signal = Signal.list["USR1"]
-        @count = 0
-        @src = @q.on_signal(@signal) {|s| @count += s.data}
-        Signal.trap(@signal, "IGNORE")
-        Process.kill(@signal, $$)
-        Process.kill(@signal, $$)
-        Signal.trap(@signal, "DEFAULT")
-        @q.sync {}
-        @count.should == 2
-        @src.cancel!
-      end
-    end    
-
-    describe "file" do
-      before :each do
-        @msg = "#{$$}-#{Time.now}"
-        @filename = "/var/tmp/gcd_spec_source-#{@msg}"
-        @file = nil
-        @src = nil
-      end
-
-      after :each do
-        @src.cancel! if not @src.nil? and not @src.cancelled?
-        @q.sync { }
-        @file.close if not @file.closed?
-        File.delete(@filename)
-      end
-
-      describe "on_read" do
-        it "fires with data on how many bytes can be read" do
-          File.open(@filename, "w") {|f| f.print @msg}
-          @file = File.open(@filename, "r")
-          @result = ""
-          @src = @q.on_read(@file) {|s| @result<<@file.read(s.data)}
-          while (@result.size < @msg.size) do; end
-          @q.sync { }
-          @result.should == @msg
-        end
-      end    
-
-      describe "on_write" do
-        it "fires with data on how many bytes can be written" do
-          @file = File.open(@filename, "w")
-          @pos = 0
-          @message = @msg
-          @src = @q.on_read(@file) do |s|
-            pos = s.data
-            if not @message.nil? then
-              next_msg = @message[0..pos-1]
-              @file.write(next_msg)
-              @message = @message[pos..-1]
-            end
-          end
-          while (@result.size < @msg.size) do; end
-          @q.sync { }
-          @result.should == @msg
-        end
-      end
-      
-      describe "on_file_event" do
-        it "fires with data on how many bytes can be written" do
-          @file = File.open(@filename, "w")
-          @fired = false
-          @src = @q.on_file_event(@file, :delete, :write, :extend, :attrib, :link, :rename, :revoke) do |s|
-              @flag = s.data
-              @fired = true
-          end
-          @file.write(@msg)
-          @file.flush
-          @q.sync { }
-          #while (@fired == false) do; end
-          @fired.should == true
-          @flag.should == Dispatch::Source.vnode_event(:write)
-        end
-      end          
-    end
-
-    describe "on_interval" do
-      it "fires with data on how often the timer has fired" do
-        @count = -1
-        repeats = 2
-        @interval = 0.02
-        @src = @q.on_interval(@interval) {|s| @count += s.data}
-        sleep repeats*@interval
-        @q.sync { }
-        @count.should == repeats
-      end
-    end
-  end
-  
-end

Copied: MacRuby/trunk/spec/macruby/library/dispatch/queue_source_spec.rb (from rev 3335, MacRuby/trunk/spec/macruby/core/gcd/prelude_spec.rb)
===================================================================
--- MacRuby/trunk/spec/macruby/library/dispatch/queue_source_spec.rb	                        (rev 0)
+++ MacRuby/trunk/spec/macruby/library/dispatch/queue_source_spec.rb	2010-01-26 00:39:08 UTC (rev 3336)
@@ -0,0 +1,146 @@
+require File.dirname(__FILE__) + "/../../spec_helper"
+require 'dispatch'
+
+if MACOSX_VERSION >= 10.6
+
+  describe "Dispatch::Queue source from" do
+    before :each do
+      @q = Dispatch::Queue.new('org.macruby.gcd_spec.prelude')
+      @src = nil
+    end
+
+    after :each do
+      @src.cancel! if not @src.nil? and not @src.cancelled?
+      @q.sync { }
+    end
+
+    describe "on_add" do
+      it "fires with data on summed inputs" do
+        @count = 0
+        @src = @q.on_add {|s| @count += s.data}
+        @src << 20
+        @src << 22
+        @q.sync {}
+        @count.should == 42
+      end
+    end    
+
+    describe "on_or" do
+      it "fires with data on ORed inputs" do
+        @count = 0
+        @src = @q.on_or {|s| @count += s.data}
+        @src << 0b101_000
+        @src << 0b000_010
+        @q.sync {}
+        @count.should == 42
+      end
+    end    
+
+    describe "on_process_event" do
+      it "fires with data indicating which process event(s)" do
+        @signal = Signal.list["USR1"]
+        @event = nil
+        @src = @q.on_process_event($$, :exit, :fork, :exec, :signal) do 
+           |s| @event = s.data
+        end
+        Signal.trap(@signal, "IGNORE")
+        Process.kill(@signal, $$)
+        Signal.trap(@signal, "DEFAULT")
+        @q.sync {}
+        @event.should == Dispatch::Source.proc_event(:signal)
+      end
+    end
+
+    describe "on_signal" do
+      it "fires with data on how often the process was signaled" do
+        @signal = Signal.list["USR1"]
+        @count = 0
+        @src = @q.on_signal(@signal) {|s| @count += s.data}
+        Signal.trap(@signal, "IGNORE")
+        Process.kill(@signal, $$)
+        Process.kill(@signal, $$)
+        Signal.trap(@signal, "DEFAULT")
+        @q.sync {}
+        @count.should == 2
+        @src.cancel!
+      end
+    end    
+
+    describe "file" do
+      before :each do
+        @msg = "#{$$}-#{Time.now}"
+        @filename = "/var/tmp/gcd_spec_source-#{@msg}"
+        @file = nil
+        @src = nil
+      end
+
+      after :each do
+        @src.cancel! if not @src.nil? and not @src.cancelled?
+        @q.sync { }
+        @file.close if not @file.closed?
+        File.delete(@filename)
+      end
+
+      describe "on_read" do
+        it "fires with data on how many bytes can be read" do
+          File.open(@filename, "w") {|f| f.print @msg}
+          @file = File.open(@filename, "r")
+          @result = ""
+          @src = @q.on_read(@file) {|s| @result<<@file.read(s.data)}
+          while (@result.size < @msg.size) do; end
+          @q.sync { }
+          @result.should == @msg
+        end
+      end    
+
+      describe "on_write" do
+        it "fires with data on how many bytes can be written" do
+          @file = File.open(@filename, "w")
+          @pos = 0
+          @message = @msg
+          @src = @q.on_read(@file) do |s|
+            pos = s.data
+            if not @message.nil? then
+              next_msg = @message[0..pos-1]
+              @file.write(next_msg)
+              @message = @message[pos..-1]
+            end
+          end
+          while (@result.size < @msg.size) do; end
+          @q.sync { }
+          @result.should == @msg
+        end
+      end
+      
+      describe "on_file_event" do
+        it "fires with data on how many bytes can be written" do
+          @file = File.open(@filename, "w")
+          @fired = false
+          @src = @q.on_file_event(@file, :delete, :write, :extend, :attrib, :link, :rename, :revoke) do |s|
+              @flag = s.data
+              @fired = true
+          end
+          @file.write(@msg)
+          @file.flush
+          @q.sync { }
+          #while (@fired == false) do; end
+          @fired.should == true
+          @flag.should == Dispatch::Source.vnode_event(:write)
+        end
+      end          
+    end
+
+    describe "on_interval" do
+      it "fires with data on how often the timer has fired" do
+        @count = -1
+        repeats = 2
+        @interval = 0.02
+        @src = @q.on_interval(@interval) {|s| @count += s.data}
+        sleep repeats*@interval
+        @q.sync { }
+        @count.should == repeats
+      end
+    end
+  end
+  
+end

Added: MacRuby/trunk/spec/macruby/library/dispatch/queue_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/library/dispatch/queue_spec.rb	                        (rev 0)
+++ MacRuby/trunk/spec/macruby/library/dispatch/queue_spec.rb	2010-01-26 00:39:08 UTC (rev 3336)
@@ -0,0 +1,27 @@
+require File.dirname(__FILE__) + "/../../spec_helper"
+require 'dispatch'
+
+if MACOSX_VERSION >= 10.6
+  describe "Dispatch::Queue" do
+    before :each do
+      @q = Dispatch::Queue.new('org.macruby.gcd_spec.prelude')
+    end
+    
+    describe "stride" do
+      it "accepts a count, stride and block and yields it that many times, with an index" do
+        @i = 0
+        @q.stride(10) { |j| @i += j; p "outer #{j}" }
+        @i.should == 45
+        @i = 0
+        @q.stride(10, 3) { |j| @i += j }
+        @i.should == 45
+        @i = 0
+        @q.stride(12, 3) { |j| @i += j }
+        @i.should == 66
+        @i = 42
+        @q.stride(0, 1) { |j| @i += 1 }
+        @i.should == 42
+      end
+    end
+  end
+end
\ No newline at end of file

Added: MacRuby/trunk/spec/macruby/tags/macruby/library/dispatch/queue_tags.txt
===================================================================
--- MacRuby/trunk/spec/macruby/tags/macruby/library/dispatch/queue_tags.txt	                        (rev 0)
+++ MacRuby/trunk/spec/macruby/tags/macruby/library/dispatch/queue_tags.txt	2010-01-26 00:39:08 UTC (rev 3336)
@@ -0,0 +1 @@
+fails:Dispatch::Queue stride accepts a count, stride and block and yields it that many times, with an index
\ No newline at end of file
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100125/fa15f5de/attachment-0001.html>


More information about the macruby-changes mailing list