[macruby-changes] [3693] MacRuby/trunk
source_changes at macosforge.org
source_changes at macosforge.org
Thu Mar 4 09:58:46 PST 2010
Revision: 3693
http://trac.macosforge.org/projects/ruby/changeset/3693
Author: ernest.prabhakar at gmail.com
Date: 2010-03-04 09:58:46 -0800 (Thu, 04 Mar 2010)
Log Message:
-----------
Let Dispatch::Source.process use mask vs. array for events
Modified Paths:
--------------
MacRuby/trunk/lib/dispatch/README.rdoc
MacRuby/trunk/lib/dispatch/source.rb
MacRuby/trunk/spec/macruby/library/dispatch/source_spec.rb
Modified: MacRuby/trunk/lib/dispatch/README.rdoc
===================================================================
--- MacRuby/trunk/lib/dispatch/README.rdoc 2010-03-04 06:03:57 UTC (rev 3692)
+++ MacRuby/trunk/lib/dispatch/README.rdoc 2010-03-04 17:58:46 UTC (rev 3693)
@@ -249,11 +249,10 @@
In addition to scheduling blocks directly, GCD makes it easy to run a block in response to various system events via a Source, which supports:
* Timers
+* Custom events
* Signals
* File descriptors and sockets
* Process state changes
-* Mach ports
-* Custom application-specific events
When the source “fires,” GCD will schedule the _handler_ block on the specific queue if it is not currently running, or -- more importantly -- coalesce pending events if it is. This provides excellent responsiveness without the expense of either polling or binding a thread to the event source. Plus, since the handler is never run more than once at a time, the block doesn’t even need to be reentrant -- and thus you don't need to +synchronize+ any variables that are only used there.
@@ -262,7 +261,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 }
- sleep 2 # => 1 1
+ sleep 2 # => 1 1 ...
=== Source#data
@@ -282,7 +281,7 @@
If you change your mind, you can always +resume!+ the source:
timer.resume!
- sleep 2 # => 2 1
+ sleep 2 # => 2 1 ...
If the +Source+ has fired one or more times, it will schedule a block containing the coalesced events. In this case, we were suspended for over 2 intervals, so the pending block will fire with +data+ being at least 2.
@@ -296,7 +295,7 @@
=== Custom Sources
-Next up are _custom_ or _application-specific_ sources, which are fired explicitly by the developer instead of in response to an external event. These can also be considered the primitive upon which other sources are built.
+Next up are _custom_ or _application-specific_ sources, which are fired explicitly by the developer instead of in response to an external event. These simple behaviors are the primitive upon which other sources are built.
==== Source.add
@@ -305,7 +304,7 @@
@sum = 0
adder = Dispatch::Source.add { |s| @sum += s.data; }
-Note that we use an instance variable (since it is re-assigned), but we don't need to +synchronize+ it since the event handler does not need to be reentrant.
+Note that we use an instance variable (since it is re-assigned), but we don't have to +synchronize+ it since the event handler does not need to be reentrant.
==== Source#<<
@@ -313,7 +312,7 @@
adder << 1 # => "add 1 -> 1"
-The name makes more sense when you see the source firing multiple times:
+The name "merge" makes more sense when you see it coalesce multiple firings into a single handler:
adder.suspend!
adder << 3
@@ -321,7 +320,7 @@
adder.resume! # => "add 8 -> 9"
adder.cancel!
-Since the block isn't running, GCD automatically _merges_ the results together using addition. This is useful for tracking cumulative results across multiple threads, e.g. for a progress viewer. Note that is also the same event coalescing behavior used by +periodic+.
+Since the source is suspended -- mimicking what would happen if your event handler was busy at the time -- GCD automatically _merges_ the results together using addition. This is useful for tracking cumulative results across multiple threads, e.g. for a progress viewer. Notice that this is also the same event coalescing behavior used by +periodic+.
==== Source.or
@@ -336,21 +335,47 @@
puts "%b" % @mask # => 1011
masker.cancel!
-This is primarily useful communicating what _kinds_ of events have taken place since the last time the handler fired.
+This is primarily useful flagging what _kinds_ of events have taken place since the last time the handler fired.
----
-= UNDER CONSTRUCTION =
-
=== Process Sources
+Next up are sources with deal with UNIX processes.
+
==== Source.process
-This +or+-style event.
+This +or+-style source takes and returns a mask of different events affecting the given process:
+exec::Dispatch::Source.PROC_EXEC
+exit::Dispatch::Source.PROC_EXIT
+fork::Dispatch::Source.PROC_FORK
+signal::Dispatch::Source.PROC_SIGNAL
+
+The API primarily treats these as integers, e.g.:
+
+ at src = Dispatch::Source.process($$, %w(exit fork exec signal),
+
+ but the wrapper allows you to optinally specify them as symbols (or strings), and convert them bitfield into an array of symbols
+
+ @signal = Signal.list["USR1"]
+ @events = []
+ @src = Dispatch::Source.process($$, %w(exit fork exec signal), @q) do
+ |s| @events = Dispatch::Source.data2events(s.data)
+ end
+ Signal.trap(@signal, "IGNORE")
+ Process.kill(@signal, $$)
+ Signal.trap(@signal, "DEFAULT")
+ @q.sync {}
+ @event.should.include? :signal > 0
+
+
+
==== Source.signal
This +add+-style event.
+---
+= UNDER CONSTRUCTION =
+
=== File Sources
==== Source.file
Modified: MacRuby/trunk/lib/dispatch/source.rb
===================================================================
--- MacRuby/trunk/lib/dispatch/source.rb 2010-03-04 06:03:57 UTC (rev 3692)
+++ MacRuby/trunk/lib/dispatch/source.rb 2010-03-04 17:58:46 UTC (rev 3693)
@@ -47,8 +47,8 @@
# Takes events: :delete, :write, :extend, :attrib, :link, :rename, :revoke
# Returns Dispatch::Source of type PROC
def process(pid, events, queue = Dispatch::Queue.concurrent, &block)
- mask = events2mask(events, @@procs)
- Dispatch::Source.new(Dispatch::Source::PROC, pid, mask, queue, &block)
+ events = events2mask(events) if not events.respond_to? :to_int
+ Dispatch::Source.new(Dispatch::Source::PROC, pid, events, queue, &block)
end
# Returns Dispatch::Source of type SIGNAL
@@ -70,7 +70,7 @@
# Takes events: :exit, :fork, :exec, :signal
# Returns Dispatch::Source of type VNODE
def file(file, events, queue = Dispatch::Queue.concurrent, &block)
- mask = events2mask(events, @@vnodes)
+ mask = events2mask(events)
Dispatch::Source.new(Dispatch::Source::VNODE, file, mask, queue, &block)
end
Modified: MacRuby/trunk/spec/macruby/library/dispatch/source_spec.rb
===================================================================
--- MacRuby/trunk/spec/macruby/library/dispatch/source_spec.rb 2010-03-04 06:03:57 UTC (rev 3692)
+++ MacRuby/trunk/spec/macruby/library/dispatch/source_spec.rb 2010-03-04 17:58:46 UTC (rev 3693)
@@ -39,16 +39,31 @@
describe "process" do
it "fires with data indicating which process event(s)" do
@signal = Signal.list["USR1"]
- @event = nil
+ @events = []
@src = Dispatch::Source.process($$, %w(exit fork exec signal), @q) do
- |s| @event = s.data
+ |s| @events += Dispatch::Source.data2events(s.data)
end
Signal.trap(@signal, "IGNORE")
Process.kill(@signal, $$)
Signal.trap(@signal, "DEFAULT")
@q.sync {}
+ @event.should.include? :signal
+ end
+
+ it "can use bitfields as well as arrays to describe events " do
+ @signal = Signal.list["USR1"]
+ mask = Dispatch::Source::PROC_EXIT | Dispatch::Source::PROC_SIGNAL
+ @event = 0
+ @src = Dispatch::Source.process($$, mask, @q) { |s| @event = s.data }
+ Signal.trap(@signal, "IGNORE")
+ Process.kill(@signal, $$)
+ Signal.trap(@signal, "DEFAULT")
+ @q.sync {}
(@event & Dispatch::Source.event2num(:signal)).should > 0
end
+
+
+
end
describe "signal" do
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macruby-changes/attachments/20100304/95665f79/attachment.html>
More information about the macruby-changes
mailing list