Skip to content
This repository has been archived by the owner on Nov 9, 2017. It is now read-only.

Commit

Permalink
Ditch the threaded event handler for a select-based event handler.
Browse files Browse the repository at this point in the history
  • Loading branch information
codahale committed May 20, 2008
1 parent 0078e9b commit 844c58c
Show file tree
Hide file tree
Showing 5 changed files with 34 additions and 36 deletions.
31 changes: 15 additions & 16 deletions lib/ropen/events/event_handler.rb
Expand Up @@ -17,15 +17,25 @@ def register(event)

def run(stdout, stderr)
call_events(:start, @command)
handle_output(stdout, :stdout)
handle_output(stderr, :stderr)
def stdout.callback ; :stdout ; end
def stderr.callback ; :stderr ; end
streams = [stdout, stderr]
until streams.empty?
selected, _ = IO.select(streams, nil, nil, 0.1)
next if selected.nil? || selected.empty?
selected.each do |stream|
if stream.eof? then
streams.delete(stream)
else
data = stream.readpartial(1024)
call_events(stream.callback, @command, data)
end
end
end
end

# Blocks until the threads started by #run completes.
def finish
@threads.each { |t| t.join }
call_events(:finish, @command)
@threads.clear
end

private
Expand All @@ -36,15 +46,4 @@ def call_events(m, *args)
end
end

def handle_output(stream, callback_method)
thread = Thread.new do
until stream.eof?
data = stream.readpartial(1024) # TODO: smaller buffer?
call_events(callback_method, @command, data)
end
end
thread.abort_on_exception = true
@threads << thread
end

end
1 change: 1 addition & 0 deletions spec/fixtures/stderr.txt
@@ -0,0 +1 @@
Blee
2 changes: 2 additions & 0 deletions spec/fixtures/stdout.txt
@@ -0,0 +1,2 @@
Blah
Blah
33 changes: 14 additions & 19 deletions spec/ropen/events/event_handler_spec.rb
Expand Up @@ -12,40 +12,35 @@
@handler = Ropen::Events::EventHandler.new(@command)
end

def pretend_to_run_stream
@stdout.should_receive(:eof?).and_return(false, false, true)
@stdout.should_receive(:readpartial).with(an_instance_of(Numeric)).and_return("blah", "blee")

@stderr.should_receive(:eof?).and_return(false, true)
@stderr.should_receive(:readpartial).with(an_instance_of(Numeric)).and_return("ERROR")

@handler.register(@event)
@handler.run(@stdout, @stderr)
@handler.finish
end

it "should register events" do
@handler.register(@event)
@handler.register(@event)
@handler.events.should == [@event, @event]
end

it "should run events on the output of a stream" do
def pretend_to_run_stream
File.open(fixture("stdout.txt")) do |f1|
File.open(fixture("stderr.txt")) do |f2|
@handler.run(f1, f2)
@handler.finish
end
end
end

it "should run events on the output of STDOUT and STDERR" do
@handler.register(@event)
@event.should_receive(:start).with(@command).ordered
@event.should_receive(:stdout).with(@command, "blah").ordered
@event.should_receive(:stdout).with(@command, "blee").ordered
@event.should_receive(:stderr).with(@command, "ERROR").ordered
@event.should_receive(:stdout).with(@command, "Blah\nBlah").ordered
@event.should_receive(:stderr).with(@command, "Blee").ordered
@event.should_receive(:finish).with(@command).ordered

pretend_to_run_stream
end

it "should catch all thrown halts" do
@event.should_receive(:start).any_number_of_times.and_throw(:halt)
@event.should_receive(:stdout).any_number_of_times.and_throw(:halt)
@event.should_receive(:stderr).any_number_of_times.and_throw(:halt)
@event.should_receive(:finish).any_number_of_times.and_throw(:halt)

@event.should_receive(:finish).any_number_of_times.and_throw(:halt)
pretend_to_run_stream
end

Expand Down
3 changes: 2 additions & 1 deletion spec/spec_helper.rb
Expand Up @@ -4,6 +4,7 @@

Spec::Runner.configure do |config|
def fixture(name)
File.join(".", "spec", "fixtures", "#{name}.rb")
filename = name.is_a?(Symbol) ? "#{name}.rb" : name
File.join(".", "spec", "fixtures", filename)
end
end

0 comments on commit 844c58c

Please sign in to comment.