Changeset 137

Show
Ignore:
Timestamp:
05/24/06 13:52:30 (4 years ago)
Author:
rosejn
Message:

- Made Base a module (was a class) and converted where needed.
- Changed to use a regular ruby array rather than the priority queue.
- Got rid of the EventManager? class that was just used for testing.
- Added the Base#verbose method so that each unit test can specify either quiet

or verbose.

- Added additional @running check to reactor run loop so we don't block if an

event has stopped the reactor.

- Renamed timer methods for adding handlers so they don't overlap with

the EventDispatcher? interface.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • experiments/machine/lib/machine/eio.rb

    r134 r137  
    1616 
    1717module Machine 
    18 class EventableIO < Base 
     18class EventableIO 
     19  include Base 
    1920  include EventDispatcher 
    2021 
     
    3233    # Then post the events. 
    3334    def run_one_cycle 
    34       $stderr.write '+' # log not defined at class level, kill this when no longer needed 
     35      @@log.debug '+' # log not defined at class level, kill this when no longer needed 
    3536      @@io_objects.delete_if {|io,obj| 
    3637        if obj.close_scheduled? 
  • experiments/machine/lib/machine/event.rb

    r125 r137  
    33 
    44  class Event 
     5    include Base 
     6 
    57    attr_reader :type 
    68 
     
    1113 
    1214  module EventDispatcher 
     15    include Base 
     16 
    1317    def initialize(*args, &block) 
    1418      @handlers = Hash.new do |hash, key|  
     
    4246    # Send an event to all the handlers for that type. 
    4347    def send_event(event) 
    44       log.debug "send_event: #{event.type}" 
     48      log.debug "\tsend_event: #{event.type}" 
    4549      @event_q << event 
    4650    end 
     
    4953    def iterate 
    5054      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}" 
    5256 
    5357        # Call handlers stored by event type 
     
    9599    end 
    96100  end 
    97  
    98   class EventManager < Base 
    99     include EventDispatcher 
    100   end 
    101  
    102101end 
  • experiments/machine/lib/machine.rb

    r133 r137  
    55  class BadHandler < Exception; end 
    66 
    7   class Base 
     7  module Base 
    88    # TODO: Figure out what we want to do for a logging framework. 
    99    @@log = Logger.new(STDERR) 
    10     @@log.level = Logger::DEBUG 
    11    #@@log.level = Logger::FATAL 
     10    @@log.level = Logger::FATAL 
    1211 
    1312    # So that all derived classes have an easy accessor 
     
    2019      @@log.level = Logger::FATAL 
    2120    end 
     21 
     22    def verbose 
     23      @@log.level = Logger::DEBUG 
     24    end 
    2225  end 
    2326 
     
    2528  require 'machine/event' 
    2629  require 'machine/timeout' 
    27   require 'machine/eio' # ADDED BY FRANCIS 
     30  require 'machine/eio'  
    2831#  require 'machine/signal' 
    2932end 
  • experiments/machine/lib/machine/reactor.rb

    r133 r137  
    22  require 'singleton' 
    33 
    4   class Reactor < Base 
     4  class Reactor 
     5    include Base 
    56    include Singleton 
    67 
     
    2021        iterate 
    2122 
    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 
    2431      end 
    2532    end 
     
    2734    def iterate 
    2835      log.debug "iterating..." 
     36 
    2937      Timeout.fire_timers 
    30       EventableIO.run_one_cycle # ADDED BY FRANCIS. 
     38      EventableIO.run_one_cycle 
     39 
    3140      @dispatchers.each {|d| d.iterate } 
    3241    end 
     
    4756    # TODO: Do we need something like crash, which stops immediately? 
    4857    #       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...? 
    4960    def stop 
    5061      log.debug "reactor stopped" 
  • experiments/machine/lib/machine/timeout.rb

    r124 r137  
    11module Machine 
    2   require 'machine/pqueue' 
    3  
    4   class Timeout < Base 
     2  class Timeout 
     3    include Base 
    54    include EventDispatcher 
    65 
    7     @@timers = PQueue.new(Proc.new {|a,b| a.expiration < b.expiration }) 
     6    @@timers = [] 
    87 
    98    class << self 
    109      # Clear out all the timers in the system. 
    11       def clear_all 
     10      def clear 
    1211        @@timers.clear 
    1312      end 
     
    1716        return 0 if @@timers.empty? 
    1817 
    19         [0, (@@timers.top.expiration - Time.now.to_i)].max 
     18        [0, (@@timers.first.expiration - Time.now.to_i)].max 
    2019      end 
    2120 
     
    2322      def fire_timers 
    2423        @@log.debug "Firing timers..." 
     24         
    2525        now = Time.now.to_i 
    2626 
    27         while(not @@timers.empty? and @@timers.top.expiration <= now) 
    28           timer = @@timers.pop  
     27        while(not @@timers.empty? and @@timers.first.expiration <= now) 
     28          timer = @@timers.shift 
    2929          timer.send_event(Event.new(:timer_expired)) if timer.alive? 
    3030        end 
     
    4343      @called = false 
    4444 
    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 
    4650       
    4751      # An an event handler to re-register if its periodic 
     
    5155    end 
    5256 
    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) 
    5559    end 
    5660 
    57     def remove_handler(src=nil) 
    58       super(:timer_expired, src) 
     61    def remove_expiration_handler(src=nil) 
     62      remove_handler(:timer_expired, src) 
    5963    end 
    6064 
     
    8589      @expiration = (Time.now + @delay).to_i 
    8690      @@timers.push self  
     91      @@timers.sort! {|a,b| a.expiration <=> b.expiration } 
    8792      log.debug "Pushed timer (#{@delay})... #{@@timers.size}" 
     93        require 'rubygems' 
     94        require 'breakpoint' 
     95        #breakpoint 
    8896    end 
    8997  end 
  • experiments/machine/test/event_test.rb

    r125 r137  
    1717  end 
    1818 
     19  class TestDispatcher 
     20    include Machine::EventDispatcher 
     21  end 
     22 
    1923  def setup 
    2024    @reactor = Reactor.instance 
    2125    @reactor.quiet 
    2226 
    23     @dispatcher = EventManager.new 
     27    @dispatcher = TestDispatcher.new 
    2428  end 
    2529 
  • experiments/machine/test/timeout_test.rb

    r125 r137  
    99  def setup 
    1010    @reactor = Reactor.instance 
    11     @reactor.quiet 
     11    @reactor.verbose 
    1212  end 
    1313 
    1414  def teardown 
    15     Timeout.clear_all 
     15    Timeout.clear 
    1616  end 
    1717 
    1818  def test_timeout 
    19     called = 0 
    20  
    2119    # Regular 
    22     Timeout.new(0) { called += 1 } 
     20    t1 = 0 
     21    Timeout.new(0) { puts "first"; t1 += 1 } 
    2322 
    2423    # Periodic 
    25     Timeout.new(1, true) { called += 1 } 
     24    t2 = 0 
     25    Timeout.new(1, true) { puts "second"; t2 += 1 } 
    2626 
    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) 
    2831 
    2932    @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 
    3142  end 
    3243 
     
    4253    @reactor.run 
    4354    assert_equal 0, called, "Cancelled timer still fired!" 
    44   end 
     55 end 
    4556end