Skip to content
Browse files

Replace callbacks/block-based instrumentation with observer

  • Loading branch information...
1 parent a8e411b commit 08818278a7a7173a5df37950c05238751170c8c6 @xavier committed Apr 15, 2012
Showing with 54 additions and 75 deletions.
  1. +23 −10 examples/test.rb
  2. +11 −29 lib/dcpu16/instrumentation.rb
  3. +20 −36 spec/instrumentation_spec.rb
View
33 examples/test.rb
@@ -6,19 +6,32 @@
require 'dcpu16'
require 'programs'
-include DCPU16::InstrumentationCallbacks
+class TestObserver
-dump_state = Proc.new { |cpu, _|
- printf("[%8d]%s\n", cpu.cycles, "-" * 80)
- DumpRegisters.call(cpu)
- DumpStack.call(cpu)
-}
+ include DCPU16::Instrumentation::Observer
+
+ def before_step(cpu)
+ printf("[%8d]%s\n", cpu.cycles, "-" * 80)
+ puts cpu.dump
+ puts cpu.stack
+ end
+
+ def after_step(cpu)
+ #gets
+ end
+
+ def before_execution(cpu, inst, a, b)
+ puts cpu.trace_instruction(inst.mnemonic, a, b)
+ end
+
+ def skipped_instruction(cpu, inst, a, b)
+ puts "*Skipped* (" + cpu.trace_instruction(inst.mnemonic, a, b) + ")"
+ end
+
+end
cpu = DCPU16::CPU.new
-cpu.on(:before_step, &dump_state)
-cpu.on(:after_step, &StepByStep)
-cpu.on(:before_execution) { |cpu, inst, a, b| puts cpu.trace_instruction(inst.mnemonic, a, b) }
-cpu.on(:skipped_instruction) { |cpu, inst, a, b| puts "*Skipped* (" + cpu.trace_instruction(inst.mnemonic, a, b) + ")" }
+cpu.add_observer(TestObserver.new)
cpu.memory.load(Programs::FACT_5)
cpu.run(50)
View
40 lib/dcpu16/instrumentation.rb
@@ -1,41 +1,23 @@
-module DCPU16
-
- module InstrumentationCallbacks
-
- DumpRegisters = Proc.new { |cpu, _| puts "Registers : #{cpu.dump}\r" }
- DumpStack = Proc.new { |cpu, _| puts "Stack : #{cpu.stack}" }
- DumpCycles = Proc.new { |cpu, _| puts "Cycles : #{cpu.cycles}" }
- DumpMemory = Proc.new { |cpu, _| puts cpu.memory.dump }
- StepByStep = Proc.new { |cpu, _| gets }
+require 'observer'
- end
+module DCPU16
module Instrumentation
- def instrumentation_callbacks
- @instrumentation_callbacks ||= {
- :before_step => [],
- :after_step => [],
- :before_execution => [],
- :after_execution => [],
- :skipped_instruction => [],
- }
- end
+ module Observer
- def instrumentation_callbacks_for(event)
- instrumentation_callbacks[event] || (raise ArgumentError.new("Unknown event: #{event.inspect}, Valid events: #{instrumentation_callbacks.keys.inspect}"))
- end
-
- def on(*events, &block)
- events.each do |event|
- instrumentation_callbacks_for(event) << block
+ def update(*args)
+ method = args.shift
+ __send__(method, *args) if respond_to?(method)
end
+
end
+ include Observable
+
def fire_callback(event, *args)
- instrumentation_callbacks_for(event).each do |proc|
- proc.call(args)
- end
+ changed(true)
+ notify_observers(*args.unshift(event))
end
end
View
56 spec/instrumentation_spec.rb
@@ -4,59 +4,43 @@
describe DCPU16::Instrumentation do
let(:cpu) { DCPU16::CPU.new }
- let(:observer) { mock() }
- describe "#on" do
+ class Observer
- it "registers a callback for a given event" do
- cpu.on(:after_step) {}
- cpu.instrumentation_callbacks[:after_step].should have(1).item
- end
-
- it "registers a callback for multiple events" do
- cpu.on(:before_step, :after_step) {}
- cpu.instrumentation_callbacks[:before_step].should have(1).item
- cpu.instrumentation_callbacks[:after_step].should have(1).item
- end
-
- it "registers multiple callbacks for a single event" do
- cpu.on(:before_step) {}
- cpu.on(:before_step) {}
- cpu.instrumentation_callbacks[:before_step].should have(2).items
- end
+ include DCPU16::Instrumentation::Observer
- it "raises an exception when given an invalid event symbol" do
- expect {
- cpu.on(:bogus) {}
- }.to raise_error(ArgumentError, /bogus/)
+ def after_step(*args)
end
end
- context "when a callback has been registered" do
-
- before do
- cpu.on(:after_step) { |args| observer.after_step(*args) }
- end
+ let(:observer) { Observer.new }
- describe '#instrumentation_callbacks_for' do
+ describe "Observer module" do
- it "returns a collection of callbacks" do
- cpu.instrumentation_callbacks_for(:after_step).should_not be_empty
- end
+ describe "#update" do
- it "returns an empty collection if the event has no callbacks" do
- cpu.instrumentation_callbacks_for(:before_step).should be_empty
+ it "dispatches the call to the method if it exists" do
+ observer.should_receive(:after_step)
+ observer.update(:after_step)
end
- it "raises an exception when given an invalid event symbol" do
+ it "does nothing if the method does not exists" do
expect {
- cpu.instrumentation_callbacks_for(:bogus)
- }.to raise_error(ArgumentError, /bogus/)
+ observer.update(:some_undefined_method)
+ }.not_to raise_error
end
end
+ end
+
+ context "when an observer has been added" do
+
+ before do
+ cpu.add_observer(observer)
+ end
+
describe '#fire_callback' do
it "invokes the callbacks for the given event with no argument" do

0 comments on commit 0881827

Please sign in to comment.
Something went wrong with that request. Please try again.