Changeset 137
- Timestamp:
- 05/24/06 13:52:30 (4 years ago)
- Files:
-
- experiments/machine/lib/machine/eio.rb (modified) (2 diffs)
- experiments/machine/lib/machine/event.rb (modified) (5 diffs)
- experiments/machine/lib/machine/pqueue.rb (deleted)
- experiments/machine/lib/machine.rb (modified) (3 diffs)
- experiments/machine/lib/machine/reactor.rb (modified) (4 diffs)
- experiments/machine/lib/machine/timeout.rb (modified) (6 diffs)
- experiments/machine/test/event_test.rb (modified) (1 diff)
- experiments/machine/test/timeout_test.rb (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
experiments/machine/lib/machine/eio.rb
r134 r137 16 16 17 17 module Machine 18 class EventableIO < Base 18 class EventableIO 19 include Base 19 20 include EventDispatcher 20 21 … … 32 33 # Then post the events. 33 34 def run_one_cycle 34 $stderr.write'+' # log not defined at class level, kill this when no longer needed35 @@log.debug '+' # log not defined at class level, kill this when no longer needed 35 36 @@io_objects.delete_if {|io,obj| 36 37 if obj.close_scheduled? experiments/machine/lib/machine/event.rb
r125 r137 3 3 4 4 class Event 5 include Base 6 5 7 attr_reader :type 6 8 … … 11 13 12 14 module EventDispatcher 15 include Base 16 13 17 def initialize(*args, &block) 14 18 @handlers = Hash.new do |hash, key| … … 42 46 # Send an event to all the handlers for that type. 43 47 def send_event(event) 44 log.debug " send_event: #{event.type}"48 log.debug "\tsend_event: #{event.type}" 45 49 @event_q << event 46 50 end … … 49 53 def iterate 50 54 while event = @event_q.shift do 51 log.debug "running handlers for event: \n\t#{event.type.inspect}"55 log.debug "running handlers for event: #{event.type}" 52 56 53 57 # Call handlers stored by event type … … 95 99 end 96 100 end 97 98 class EventManager < Base99 include EventDispatcher100 end101 102 101 end experiments/machine/lib/machine.rb
r133 r137 5 5 class BadHandler < Exception; end 6 6 7 classBase7 module Base 8 8 # TODO: Figure out what we want to do for a logging framework. 9 9 @@log = Logger.new(STDERR) 10 @@log.level = Logger::DEBUG 11 #@@log.level = Logger::FATAL 10 @@log.level = Logger::FATAL 12 11 13 12 # So that all derived classes have an easy accessor … … 20 19 @@log.level = Logger::FATAL 21 20 end 21 22 def verbose 23 @@log.level = Logger::DEBUG 24 end 22 25 end 23 26 … … 25 28 require 'machine/event' 26 29 require 'machine/timeout' 27 require 'machine/eio' # ADDED BY FRANCIS30 require 'machine/eio' 28 31 # require 'machine/signal' 29 32 end experiments/machine/lib/machine/reactor.rb
r133 r137 2 2 require 'singleton' 3 3 4 class Reactor < Base 4 class Reactor 5 include Base 5 6 include Singleton 6 7 … … 20 21 iterate 21 22 22 log.debug("run loop sleeping for #{Timeout.next} seconds...") 23 IO.select(nil, nil, nil, Timeout.next) 23 # If the reactor was stopped while dispatching events we don't want to 24 # block again. 25 if @running 26 log.debug("run loop sleeping for #{Timeout.next} seconds...") 27 28 # TODO: Figure out the best behavior here... 29 IO.select(nil, nil, nil, Timeout.next || 0.1) 30 end 24 31 end 25 32 end … … 27 34 def iterate 28 35 log.debug "iterating..." 36 29 37 Timeout.fire_timers 30 EventableIO.run_one_cycle # ADDED BY FRANCIS. 38 EventableIO.run_one_cycle 39 31 40 @dispatchers.each {|d| d.iterate } 32 41 end … … 47 56 # TODO: Do we need something like crash, which stops immediately? 48 57 # This will stop after the current loop completes processing. 58 # TODO: Maybe the reactor should be a dispatcher also, so we can send out 59 # system events for startup, shutdown, reset etc...? 49 60 def stop 50 61 log.debug "reactor stopped" experiments/machine/lib/machine/timeout.rb
r124 r137 1 1 module Machine 2 require 'machine/pqueue' 3 4 class Timeout < Base 2 class Timeout 3 include Base 5 4 include EventDispatcher 6 5 7 @@timers = PQueue.new(Proc.new {|a,b| a.expiration < b.expiration })6 @@timers = [] 8 7 9 8 class << self 10 9 # Clear out all the timers in the system. 11 def clear _all10 def clear 12 11 @@timers.clear 13 12 end … … 17 16 return 0 if @@timers.empty? 18 17 19 [0, (@@timers. top.expiration - Time.now.to_i)].max18 [0, (@@timers.first.expiration - Time.now.to_i)].max 20 19 end 21 20 … … 23 22 def fire_timers 24 23 @@log.debug "Firing timers..." 24 25 25 now = Time.now.to_i 26 26 27 while(not @@timers.empty? and @@timers. top.expiration <= now)28 timer = @@timers. pop27 while(not @@timers.empty? and @@timers.first.expiration <= now) 28 timer = @@timers.shift 29 29 timer.send_event(Event.new(:timer_expired)) if timer.alive? 30 30 end … … 43 43 @called = false 44 44 45 add_handler(&block) if block 45 if @periodic 46 add_expiration_handler {|event| register_timer; block.call(event) } 47 else 48 add_expiration_handler(&block) if block 49 end 46 50 47 51 # An an event handler to re-register if its periodic … … 51 55 end 52 56 53 def add_ handler(src=nil, handler=nil, &block)54 super(:timer_expired, src, handler, &block)57 def add_expiration_handler(src=nil, handler=nil, &block) 58 add_handler(:timer_expired, src, handler, &block) 55 59 end 56 60 57 def remove_ handler(src=nil)58 super(:timer_expired, src)61 def remove_expiration_handler(src=nil) 62 remove_handler(:timer_expired, src) 59 63 end 60 64 … … 85 89 @expiration = (Time.now + @delay).to_i 86 90 @@timers.push self 91 @@timers.sort! {|a,b| a.expiration <=> b.expiration } 87 92 log.debug "Pushed timer (#{@delay})... #{@@timers.size}" 93 require 'rubygems' 94 require 'breakpoint' 95 #breakpoint 88 96 end 89 97 end experiments/machine/test/event_test.rb
r125 r137 17 17 end 18 18 19 class TestDispatcher 20 include Machine::EventDispatcher 21 end 22 19 23 def setup 20 24 @reactor = Reactor.instance 21 25 @reactor.quiet 22 26 23 @dispatcher = EventManager.new27 @dispatcher = TestDispatcher.new 24 28 end 25 29 experiments/machine/test/timeout_test.rb
r125 r137 9 9 def setup 10 10 @reactor = Reactor.instance 11 @reactor. quiet11 @reactor.verbose 12 12 end 13 13 14 14 def teardown 15 Timeout.clear _all15 Timeout.clear 16 16 end 17 17 18 18 def test_timeout 19 called = 020 21 19 # Regular 22 Timeout.new(0) { called += 1 } 20 t1 = 0 21 Timeout.new(0) { puts "first"; t1 += 1 } 23 22 24 23 # Periodic 25 Timeout.new(1, true) { called += 1 } 24 t2 = 0 25 Timeout.new(1, true) { puts "second"; t2 += 1 } 26 26 27 Timeout.new(2) { @reactor.stop } 27 # Method based 28 @t3 = 0 29 timer = Timeout.new(3) 30 timer.add_expiration_handler(self, :stop_reactor) 28 31 29 32 @reactor.run 30 assert_equal 3, called, "Timers not firing!" 33 assert_equal 1, t1, "Regular block timer did not fire." 34 assert_equal 3, t2, "Periodic block timer did not fire enough." 35 assert_equal 1, @t3, "Method based timer did not fire." 36 end 37 38 def stop_reactor(event) 39 puts "third..." 40 @t3 += 1 41 @reactor.stop 31 42 end 32 43 … … 42 53 @reactor.run 43 54 assert_equal 0, called, "Cancelled timer still fired!" 44 55 end 45 56 end