spnet 0.1.2 → 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
data/ChangeLog.rdoc CHANGED
@@ -11,4 +11,11 @@ Updated to use hashmake 0.1.1 gem.
11
11
  * Update project files, including:
12
12
  ** Removing README.md so that YARD can run without needing the redcarpet gem.
13
13
  ** Removing unnecessary lines from .gitignore
14
- ** Remove specific hashmake version in hashmake.gemspec
14
+ ** Remove specific hashmake version in hashmake.gemspec
15
+
16
+ === 0.1.3 / 2013-02-06
17
+
18
+ Replace messages and message ports with more specific ports, like value ports and command ports, and use a base InPort and OutPort to share code for linking ports.
19
+ Each kind of port can only connect to its opposite (e.g. SignaInPort to SignalOutPort).
20
+ Instead of different messages for different actions, each kind of port will just have specific methods (e.g. SignalInPort#enqueue_values or ValueInPort#set_value).
21
+ In Block, contain all InPort objects in @in_ports, and all OutPort objects in @out_ports.
data/README.rdoc CHANGED
@@ -6,10 +6,16 @@
6
6
 
7
7
  == Description
8
8
 
9
- TODO: Description
9
+ Provide infrastructure for forming processing networks.
10
10
 
11
11
  == Features
12
12
 
13
+ Signal ports: Used to pass a stream of data through a block.
14
+
15
+ Value ports: Used to get/set a value within a block (usually to control a parameter), with optional range limiting.
16
+
17
+ Command ports: Used to trigger the execution a command within a block, with optional data as well.
18
+
13
19
  == Examples
14
20
 
15
21
  require 'spnet'
data/lib/spnet/block.rb CHANGED
@@ -3,17 +3,15 @@ module SPNet
3
3
  class Block
4
4
  include Hashmake::HashMakeable
5
5
 
6
- attr_reader :name, :signal_in_ports, :signal_out_ports, :message_in_ports, :message_out_ports
6
+ attr_reader :name, :in_ports, :out_ports
7
7
 
8
8
  DO_NOTHING = ->(){}
9
9
 
10
10
  HASHED_ARG_SPECS = [
11
11
  Hashmake::ArgSpec.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
12
12
  Hashmake::ArgSpec.new(:reqd => false, :key => :algorithm, :type => Proc, :default => DO_NOTHING),
13
- Hashmake::ArgSpec.new(:reqd => false, :key => :signal_in_ports, :type => SignalInPort, :array => true, :default => ->(){ Array.new } ),
14
- Hashmake::ArgSpec.new(:reqd => false, :key => :signal_out_ports, :type => SignalOutPort, :array => true, :default => ->(){ Array.new }),
15
- Hashmake::ArgSpec.new(:reqd => false, :key => :message_in_ports, :type => MessageInPort, :array => true, :default => ->(){ Array.new }),
16
- Hashmake::ArgSpec.new(:reqd => false, :key => :message_out_ports, :type => MessageOutPort, :array => true, :default => ->(){ Array.new })
13
+ Hashmake::ArgSpec.new(:reqd => false, :key => :in_ports, :type => InPort, :array => true, :default => ->(){ Array.new } ),
14
+ Hashmake::ArgSpec.new(:reqd => false, :key => :out_ports, :type => OutPort, :array => true, :default => ->(){ Array.new }),
17
15
  ]
18
16
 
19
17
  def initialize args = {}
@@ -21,7 +19,7 @@ class Block
21
19
  end
22
20
 
23
21
  def find_ports name, ignore_case = true
24
- matches = (@signal_in_ports + @signal_out_ports + @message_in_ports + @message_out_ports).select do |port|
22
+ matches = (@in_ports + @out_ports).select do |port|
25
23
  if ignore_case
26
24
  port.name.casecmp(name) == 0
27
25
  else
@@ -0,0 +1,29 @@
1
+ require 'hashmake'
2
+
3
+ module SPNet
4
+ class InPort
5
+
6
+ include Hashmake::HashMakeable
7
+
8
+ ARG_SPECS = [
9
+ Hashmake::ArgSpec.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
10
+ Hashmake::ArgSpec.new(:reqd => true, :key => :matching_port_class, :type => Class),
11
+ ]
12
+
13
+ attr_reader :name, :link
14
+
15
+ def initialize args
16
+ hash_make InPort::ARG_SPECS, args
17
+ @link = nil
18
+ end
19
+
20
+ def clear_link
21
+ @link = nil
22
+ end
23
+
24
+ def set_link link
25
+ raise ArgumentError, "link #{link} is not a #{@matching_port_class}" unless link.is_a?(@matching_port_class)
26
+ @link = link
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,64 @@
1
+ require 'set'
2
+ require 'hashmake'
3
+
4
+ module SPNet
5
+ class OutPort
6
+
7
+ include Hashmake::HashMakeable
8
+
9
+ ARG_SPECS = [
10
+ Hashmake::ArgSpec.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
11
+ Hashmake::ArgSpec.new(:reqd => true, :key => :matching_port_class, :type => Class),
12
+ ]
13
+
14
+ attr_reader :name, :links
15
+
16
+ def initialize hashed_args = {}
17
+ hash_make OutPort::ARG_SPECS, hashed_args
18
+ @links = Set.new
19
+ end
20
+
21
+ def add_link link
22
+ raise ArgumentError, "link #{link} is not a #{@matching_port_class}" unless link.is_a?(@matching_port_class)
23
+ raise ArgumentError, "link #{link} is already linked" if link.link
24
+ @links.add link
25
+ link.set_link self
26
+ end
27
+
28
+ def remove_link link
29
+ raise ArgumentError, "@links does not include link #{link}" unless @links.include? link
30
+ @links.delete link
31
+ link.clear_link
32
+ end
33
+
34
+ def remove_bad_links
35
+ find_bad_links_and :remove
36
+ end
37
+
38
+ def correct_bad_links
39
+ find_bad_links_and :correct
40
+ end
41
+
42
+ private
43
+
44
+ def find_bad_links_and action
45
+ marked = []
46
+
47
+ @links.each do |link|
48
+ bad = (link.link == nil) or (link.link != self)
49
+ if bad
50
+ marked.push link
51
+ end
52
+ end
53
+
54
+ marked.each do |link|
55
+ if action == :remove
56
+ @links.delete link
57
+ elsif action == :correct
58
+ link.set_link self
59
+ end
60
+ end
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,27 @@
1
+ require 'hashmake'
2
+
3
+ module SPNet
4
+ class CommandInPort < InPort
5
+
6
+ include Hashmake::HashMakeable
7
+
8
+ ARG_SPECS = [
9
+ Hashmake::ArgSpec.new(:key => :list_commands_handler, :reqd => true, :type => Proc),
10
+ Hashmake::ArgSpec.new(:key => :exec_command_handler, :reqd => true, :type => Proc)
11
+ ]
12
+
13
+ def initialize hashed_args
14
+ hash_make(CommandInPort::ARG_SPECS, hashed_args)
15
+ hashed_args.merge!(:matching_port_class => CommandOutPort)
16
+ super(hashed_args)
17
+ end
18
+
19
+ def list_commands
20
+ @list_commands_handler.call
21
+ end
22
+
23
+ def exec_command command, data
24
+ @exec_command_handler.call command, data
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,26 @@
1
+ module SPNet
2
+ class CommandOutPort < OutPort
3
+
4
+ def initialize hashed_args = {}
5
+ hashed_args.merge!(:matching_port_class => CommandInPort)
6
+ super(hashed_args)
7
+ end
8
+
9
+ def list_commands
10
+ rvs = []
11
+ @links.each do |link|
12
+ rvs.push link.list_commands
13
+ end
14
+ return rvs
15
+ end
16
+
17
+ def exec_command command, data = nil
18
+ rvs = []
19
+ @links.each do |link|
20
+ rvs.push link.exec_command(command, data)
21
+ end
22
+ return rvs
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,43 @@
1
+ require 'hashmake'
2
+ require 'spcore'
3
+
4
+ module SPNet
5
+ class SignalInPort < InPort
6
+
7
+ include Hashmake::HashMakeable
8
+
9
+ DEFAULT_LIMITS = (-Float::MAX..Float::MAX)
10
+
11
+ ARG_SPECS = [
12
+ Hashmake::ArgSpec.new(:reqd => false, :key => :limits, :type => Range, :default => DEFAULT_LIMITS)
13
+ ]
14
+
15
+ attr_reader :limits, :queue
16
+
17
+ def initialize hashed_args = {}
18
+ hash_make(SignalInPort::ARG_SPECS, hashed_args)
19
+ @queue = []
20
+ @skip_limiting = (@limits == DEFAULT_LIMITS)
21
+ @limiter = SPCore::Limiters.make_range_limiter @limits
22
+
23
+ hashed_args.merge!(:matching_port_class => SignalOutPort)
24
+ super(hashed_args)
25
+ end
26
+
27
+ def enqueue_values values
28
+ unless @skip_limiting
29
+ for i in 0...values.count
30
+ values[i] = @limiter.call(values[i])
31
+ end
32
+ end
33
+
34
+ @queue.concat values
35
+ end
36
+
37
+ def dequeue_values count = @queue.count
38
+ raise ArgumentError, "count is greater than @queue.count" if count > @queue.count
39
+ @queue.slice!(0...count)
40
+ end
41
+
42
+ end
43
+ end
@@ -0,0 +1,18 @@
1
+ require 'set'
2
+
3
+ module SPNet
4
+ class SignalOutPort < OutPort
5
+
6
+ def initialize hashed_args = {}
7
+ hashed_args.merge!(:matching_port_class => SignalInPort)
8
+ super(hashed_args)
9
+ end
10
+
11
+ def send_values values
12
+ @links.each do |link|
13
+ link.enqueue_values values
14
+ end
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ require 'hashmake'
2
+
3
+ module SPNet
4
+ class ValueInPort < InPort
5
+
6
+ include Hashmake::HashMakeable
7
+
8
+ ARG_SPECS = [
9
+ Hashmake::ArgSpec.new(:key => :get_value_handler, :reqd => true, :type => Proc),
10
+ Hashmake::ArgSpec.new(:key => :set_value_handler, :reqd => true, :type => Proc)
11
+ ]
12
+
13
+ def initialize hashed_args = {}
14
+ hash_make(ValueInPort::ARG_SPECS, hashed_args)
15
+ hashed_args.merge!(:matching_port_class => ValueOutPort)
16
+ super(hashed_args)
17
+ end
18
+
19
+ def set_value value
20
+ @set_value_handler.call value
21
+ end
22
+
23
+ def get_value
24
+ @get_value_handler.call
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,28 @@
1
+ require 'set'
2
+
3
+ module SPNet
4
+ class ValueOutPort < OutPort
5
+
6
+ def initialize hashed_args = {}
7
+ hashed_args.merge!(:matching_port_class => ValueInPort)
8
+ super(hashed_args)
9
+ end
10
+
11
+ def set_value value
12
+ rvs = []
13
+ @links.each do |link|
14
+ rvs.push link.set_value value
15
+ end
16
+ return rvs
17
+ end
18
+
19
+ def get_value
20
+ rvs = []
21
+ @links.each do |link|
22
+ rvs.push link.get_value
23
+ end
24
+ return rvs
25
+ end
26
+
27
+ end
28
+ end
data/lib/spnet/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
  module SPNet
2
2
  # spnet version
3
- VERSION = "0.1.2"
3
+ VERSION = "0.1.3"
4
4
  end
data/lib/spnet.rb CHANGED
@@ -1,9 +1,11 @@
1
1
  require 'spnet/version'
2
-
3
- require 'spnet/signal_in_port'
4
- require 'spnet/signal_out_port'
5
- require 'spnet/message'
6
- require 'spnet/control_message'
7
- require 'spnet/message_in_port'
8
- require 'spnet/message_out_port'
2
+ require 'spnet/in_port'
3
+ require 'spnet/out_port'
9
4
  require 'spnet/block'
5
+
6
+ require 'spnet/ports/signal_in_port'
7
+ require 'spnet/ports/signal_out_port'
8
+ require 'spnet/ports/value_in_port'
9
+ require 'spnet/ports/value_out_port'
10
+ require 'spnet/ports/command_in_port'
11
+ require 'spnet/ports/command_out_port'
data/spec/block_spec.rb CHANGED
@@ -8,30 +8,30 @@ describe SPNet::Block do
8
8
  end
9
9
 
10
10
  it 'should have no input ports' do
11
- @block.signal_in_ports.should be_empty
11
+ @block.in_ports.should be_empty
12
12
  end
13
13
 
14
14
  it 'should have no output ports' do
15
- @block.signal_out_ports.should be_empty
15
+ @block.out_ports.should be_empty
16
16
  end
17
17
  end
18
18
 
19
- context '1 signal in and 1 signal out port given' do
19
+ context '1 in and 1 out port given' do
20
20
  before :all do
21
21
  @block = SPNet::Block.new(
22
- :signal_in_ports => [SPNet::SignalInPort.new(:name => "IN")],
23
- :signal_out_ports => [SPNet::SignalOutPort.new(:name => "OUT")],
22
+ :in_ports => [SPNet::SignalInPort.new(:name => "IN")],
23
+ :out_ports => [SPNet::SignalOutPort.new(:name => "OUT")],
24
24
  )
25
25
  end
26
26
 
27
- it 'should have no input ports' do
28
- @block.signal_in_ports.count.should be 1
29
- @block.signal_in_ports.first.name.should eq("IN")
27
+ it 'should have 1 input port' do
28
+ @block.in_ports.count.should be 1
29
+ @block.in_ports.first.name.should eq("IN")
30
30
  end
31
31
 
32
- it 'should have no output ports' do
33
- @block.signal_out_ports.count.should be 1
34
- @block.signal_out_ports.first.name.should eq("OUT")
32
+ it 'should have 1 output port' do
33
+ @block.out_ports.count.should be 1
34
+ @block.out_ports.first.name.should eq("OUT")
35
35
  end
36
36
  end
37
37
  end
@@ -0,0 +1,29 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ describe SPNet::InPort do
4
+ describe '.new' do
5
+ it 'should not have any links' do
6
+ port = SPNet::InPort.new :matching_port_class => SPNet::OutPort
7
+ port.link.should be_nil
8
+ end
9
+ end
10
+
11
+ describe '#set_link' do
12
+ it 'should set link to given OutPort' do
13
+ in_port = SPNet::InPort.new :matching_port_class => SPNet::OutPort
14
+ out_port = SPNet::OutPort.new :matching_port_class => SPNet::InPort
15
+ in_port.set_link out_port
16
+ in_port.link.should eq(out_port)
17
+ end
18
+ end
19
+
20
+ describe '#clear_link' do
21
+ it 'should set link to given OutPort' do
22
+ in_port = SPNet::InPort.new :matching_port_class => SPNet::OutPort
23
+ out_port = SPNet::OutPort.new :matching_port_class => SPNet::InPort
24
+ in_port.set_link out_port
25
+ in_port.clear_link
26
+ in_port.link.should be_nil
27
+ end
28
+ end
29
+ end
@@ -1,21 +1,17 @@
1
1
  require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
2
 
3
- describe SPNet::MessageOutPort do
4
- before :all do
5
- processor = lambda do |message|
6
- return message
7
- end
8
- @in_port = SPNet::MessageInPort.new :processor => processor, :message_type => SPNet::Message::CONTROL
9
- end
10
-
3
+ describe SPNet::OutPort do
11
4
  before :each do
12
- processor = lambda do |message|
13
- return message
14
- end
15
- @in_port = SPNet::MessageInPort.new :processor => processor, :message_type => SPNet::Message::CONTROL
16
- @out_port = SPNet::MessageOutPort.new
5
+ @in_port = SPNet::InPort.new :matching_port_class => SPNet::OutPort
6
+ @out_port = SPNet::OutPort.new :matching_port_class => SPNet::InPort
17
7
  end
18
-
8
+
9
+ describe '.new' do
10
+ it 'should have no links' do
11
+ @out_port.links.should be_empty
12
+ end
13
+ end
14
+
19
15
  describe '#add_link' do
20
16
  it 'should add the given input port to links' do
21
17
  @out_port.add_link @in_port
@@ -34,8 +30,8 @@ describe SPNet::MessageOutPort do
34
30
  end
35
31
 
36
32
  it 'should raise ArgumentError if port is not input port' do
37
- @out_port2 = SPNet::MessageOutPort.new
38
- lambda { @out_port.add_link(@out_port2) }.should raise_error(ArgumentError)
33
+ out_port2 = SPNet::OutPort.new :matching_port_class => SPNet::InPort
34
+ lambda { @out_port.add_link(out_port2) }.should raise_error(ArgumentError)
39
35
  end
40
36
  end
41
37
 
@@ -46,12 +42,5 @@ describe SPNet::MessageOutPort do
46
42
  @out_port.links.should be_empty
47
43
  end
48
44
  end
49
-
50
- describe '#send_message' do
51
- it 'should pass the given message via recv_message to the processing callback' do
52
- @out_port.add_link @in_port
53
- rv = @out_port.send_message SPNet::ControlMessage.make_set_message(5)
54
- rv.first.data.should eq(5)
55
- end
56
- end
45
+
57
46
  end
@@ -0,0 +1,42 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SPNet::CommandInPort do
4
+ before :each do
5
+ @commands = ["add", "sub", "mul", "div"]
6
+
7
+ list_commands_handler = lambda { return @commands }
8
+
9
+ exec_command_handler = lambda do |command, data|
10
+ x = data[0]
11
+ y = data[1]
12
+
13
+ case command
14
+ when "add"
15
+ return x + y
16
+ when "sub"
17
+ return x - y
18
+ when "mul"
19
+ return x * y
20
+ when "div"
21
+ return x / y
22
+ end
23
+ end
24
+
25
+ @port = SPNet::CommandInPort.new :list_commands_handler => list_commands_handler, :exec_command_handler => exec_command_handler
26
+ end
27
+
28
+ describe '#list_commands' do
29
+ it 'should pass back the return value from the list_commands handler' do
30
+ @port.list_commands.should eq(@commands)
31
+ end
32
+ end
33
+
34
+ describe '#exec_command' do
35
+ it 'should pass the command and data to the exec_command handler, and pass back the return value' do
36
+ @port.exec_command("add", [1,2]).should eq(3)
37
+ @port.exec_command("sub", [5,4]).should eq(1)
38
+ @port.exec_command("mul", [3,2]).should eq(6)
39
+ @port.exec_command("div", [9,3]).should eq(3)
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SPNet::ValueOutPort do
4
+ before :each do
5
+ @commands = ["add", "sub", "mul", "div"]
6
+
7
+ list_commands_handler = lambda { return @commands }
8
+
9
+ exec_command_handler = lambda do |command, data|
10
+ x = data[0]
11
+ y = data[1]
12
+
13
+ case command
14
+ when "add"
15
+ return x + y
16
+ when "sub"
17
+ return x - y
18
+ when "mul"
19
+ return x * y
20
+ when "div"
21
+ return x / y
22
+ end
23
+ end
24
+
25
+ @in_port = SPNet::CommandInPort.new :list_commands_handler => list_commands_handler, :exec_command_handler => exec_command_handler
26
+ @out_port = SPNet::CommandOutPort.new
27
+ end
28
+
29
+ describe '#add_link' do
30
+ it 'should raise ArgumentError if port is not ValueInPort' do
31
+ @in_port2 = SPNet::SignalInPort.new
32
+ lambda { @out_port.add_link(@in_port2) }.should raise_error(ArgumentError)
33
+ end
34
+ end
35
+
36
+ describe '#list_commands' do
37
+ it 'should pass back the return value from the list_commands handler' do
38
+ @out_port.add_link @in_port
39
+ @out_port.list_commands.should eq([@commands])
40
+ end
41
+ end
42
+
43
+ describe '#exec_command' do
44
+ it 'should pass the command and data to the exec_command handler, and pass back the return value' do
45
+ @out_port.add_link @in_port
46
+ @out_port.exec_command("add", [1,2]).should eq([3])
47
+ @out_port.exec_command("sub", [5,4]).should eq([1])
48
+ @out_port.exec_command("mul", [3,2]).should eq([6])
49
+ @out_port.exec_command("div", [9,3]).should eq([3])
50
+ end
51
+ end
52
+
53
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe SPNet::SignalInPort do
4
4
  describe '.new' do
@@ -1,4 +1,4 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
2
 
3
3
  describe SPNet::SignalOutPort do
4
4
  before :each do
@@ -6,44 +6,13 @@ describe SPNet::SignalOutPort do
6
6
  @in_port = SPNet::SignalInPort.new
7
7
  end
8
8
 
9
- describe '.new' do
10
- it 'should have no links' do
11
- @out_port = SPNet::SignalOutPort.new
12
- @out_port.links.should be_empty
13
- end
14
- end
15
-
16
- describe '#add_link' do
17
- it 'should add the given input port to links' do
18
- @out_port.add_link @in_port
19
- @out_port.links.count.should be 1
20
- @out_port.links.first.should eq(@in_port)
21
- end
22
-
23
- it 'should also link the output port to the given input port' do
24
- @out_port.add_link @in_port
25
- @in_port.link.should eq(@out_port)
26
- end
27
-
28
- it 'should raise ArgumentError if the given input port is already linked' do
29
- @out_port.add_link @in_port
30
- lambda { @out_port.add_link(@in_port) }.should raise_error(ArgumentError)
31
- end
32
-
9
+ describe '#add_link' do
33
10
  it 'should raise ArgumentError if port is not input port' do
34
11
  out_port2 = SPNet::SignalOutPort.new
35
12
  lambda { @out_port.add_link(out_port2) }.should raise_error(ArgumentError)
36
13
  end
37
14
  end
38
15
 
39
- describe '#remove_link' do
40
- it 'should remove the given input port (if it is already linked to the output port)' do
41
- @out_port.add_link @in_port
42
- @out_port.remove_link @in_port
43
- @out_port.links.should be_empty
44
- end
45
- end
46
-
47
16
  describe '#send_values' do
48
17
  context 'single linked input port' do
49
18
  it 'should enqueue the values on the linked input port' do
@@ -0,0 +1,31 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SPNet::ValueInPort do
4
+ before :each do
5
+ @value = 0
6
+
7
+ set_value_handler = lambda do |value|
8
+ return @value = value
9
+ end
10
+
11
+ get_value_handler = lambda do
12
+ return @value
13
+ end
14
+
15
+ @port = SPNet::ValueInPort.new :get_value_handler => get_value_handler, :set_value_handler => set_value_handler
16
+ end
17
+
18
+ describe '#set_value' do
19
+ it 'should pass the given value through the set_value handler' do
20
+ rv = @port.set_value 5
21
+ @value.should eq(5)
22
+ end
23
+ end
24
+
25
+ describe '#get_value' do
26
+ it 'should return the value from the get_value handler' do
27
+ @value = 7
28
+ @port.get_value.should eq(7)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,41 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe SPNet::ValueOutPort do
4
+ before :each do
5
+ @value = 0
6
+
7
+ set_value_handler = lambda do |value|
8
+ return @value = value
9
+ end
10
+
11
+ get_value_handler = lambda do
12
+ return @value
13
+ end
14
+
15
+ @out_port = SPNet::ValueOutPort.new
16
+ @in_port = SPNet::ValueInPort.new :get_value_handler => get_value_handler, :set_value_handler => set_value_handler
17
+ end
18
+
19
+ describe '#add_link' do
20
+ it 'should raise ArgumentError if port is not ValueInPort' do
21
+ @in_port2 = SPNet::SignalInPort.new
22
+ lambda { @out_port.add_link(@in_port2) }.should raise_error(ArgumentError)
23
+ end
24
+ end
25
+
26
+ describe '#set_value' do
27
+ it 'should pass the given value through ValueInPort#set_value' do
28
+ @out_port.add_link @in_port
29
+ rv = @out_port.set_value 5
30
+ @value.should eq(5)
31
+ end
32
+ end
33
+
34
+ describe '#get_value' do
35
+ it "should return the value from each linked port's ValueInPort#get_value" do
36
+ @value = 7
37
+ @out_port.add_link @in_port
38
+ @out_port.get_value.first.should eq(7)
39
+ end
40
+ end
41
+ end
File without changes
data/spnet.gemspec CHANGED
@@ -20,6 +20,7 @@ DESCRIPTION
20
20
  gem.require_paths = ['lib']
21
21
 
22
22
  gem.add_dependency 'hashmake'
23
+ gem.add_dependency 'spcore'
23
24
 
24
25
  gem.add_development_dependency 'bundler', '~> 1.0'
25
26
  gem.add_development_dependency 'rake', '~> 0.8'
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: spnet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2013-02-04 00:00:00.000000000 Z
12
+ date: 2013-02-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hashmake
@@ -27,6 +27,22 @@ dependencies:
27
27
  - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
29
  version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: spcore
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: bundler
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -126,22 +142,26 @@ files:
126
142
  - Rakefile
127
143
  - lib/spnet.rb
128
144
  - lib/spnet/block.rb
129
- - lib/spnet/control_message.rb
130
- - lib/spnet/message.rb
131
- - lib/spnet/message_in_port.rb
132
- - lib/spnet/message_out_port.rb
133
- - lib/spnet/signal_in_port.rb
134
- - lib/spnet/signal_out_port.rb
145
+ - lib/spnet/in_port.rb
146
+ - lib/spnet/out_port.rb
147
+ - lib/spnet/ports/command_in_port.rb
148
+ - lib/spnet/ports/command_out_port.rb
149
+ - lib/spnet/ports/signal_in_port.rb
150
+ - lib/spnet/ports/signal_out_port.rb
151
+ - lib/spnet/ports/value_in_port.rb
152
+ - lib/spnet/ports/value_out_port.rb
135
153
  - lib/spnet/version.rb
136
154
  - spec/block_spec.rb
137
- - spec/control_message_spec.rb
138
- - spec/message_in_port_spec.rb
139
- - spec/message_out_port_spec.rb
140
- - spec/message_spec.rb
141
- - spec/signal_in_port_spec.rb
142
- - spec/signal_out_port_spec.rb
155
+ - spec/in_port_spec.rb
156
+ - spec/out_port_spec.rb
157
+ - spec/ports/command_in_port_spec.rb
158
+ - spec/ports/command_out_port_spec.rb
159
+ - spec/ports/signal_in_port_spec.rb
160
+ - spec/ports/signal_out_port_spec.rb
161
+ - spec/ports/value_in_port_spec.rb
162
+ - spec/ports/value_out_port_spec.rb
143
163
  - spec/spec_helper.rb
144
- - spec/spnetwork_spec.rb
164
+ - spec/spnet_spec.rb
145
165
  - spnet.gemspec
146
166
  homepage: https://rubygems.org/gems/spnet
147
167
  licenses:
@@ -158,7 +178,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
158
178
  version: '0'
159
179
  segments:
160
180
  - 0
161
- hash: 402444883
181
+ hash: -270931181
162
182
  required_rubygems_version: !ruby/object:Gem::Requirement
163
183
  none: false
164
184
  requirements:
@@ -167,7 +187,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
167
187
  version: '0'
168
188
  segments:
169
189
  - 0
170
- hash: 402444883
190
+ hash: -270931181
171
191
  requirements: []
172
192
  rubyforge_project:
173
193
  rubygems_version: 1.8.23
@@ -176,12 +196,14 @@ specification_version: 3
176
196
  summary: Provide infrastructure for forming processing networks.
177
197
  test_files:
178
198
  - spec/block_spec.rb
179
- - spec/control_message_spec.rb
180
- - spec/message_in_port_spec.rb
181
- - spec/message_out_port_spec.rb
182
- - spec/message_spec.rb
183
- - spec/signal_in_port_spec.rb
184
- - spec/signal_out_port_spec.rb
199
+ - spec/in_port_spec.rb
200
+ - spec/out_port_spec.rb
201
+ - spec/ports/command_in_port_spec.rb
202
+ - spec/ports/command_out_port_spec.rb
203
+ - spec/ports/signal_in_port_spec.rb
204
+ - spec/ports/signal_out_port_spec.rb
205
+ - spec/ports/value_in_port_spec.rb
206
+ - spec/ports/value_out_port_spec.rb
185
207
  - spec/spec_helper.rb
186
- - spec/spnetwork_spec.rb
208
+ - spec/spnet_spec.rb
187
209
  has_rdoc:
@@ -1,52 +0,0 @@
1
- require 'hashmake'
2
-
3
- module SPNet
4
- class ControlMessage < Message
5
-
6
- include Hashmake::HashMakeable
7
-
8
- GET = :controlMessageSubtypeGet
9
- SET = :controlMessageSubtypeSet
10
-
11
- SUBTYPES = [
12
- GET,
13
- SET
14
- ]
15
-
16
- HASHED_ARGS_SPECS = [
17
- Hashmake::ArgSpec.new(:reqd => true, :key => :subtype, :type => Symbol, :validator => ->(a){ SUBTYPES.include?(a) } )
18
- ]
19
-
20
- attr_reader :subtype
21
-
22
- def initialize hashed_args
23
- hash_make ControlMessage::HASHED_ARGS_SPECS, hashed_args
24
- super_hashed_args = hashed_args.merge! :type => Message::CONTROL
25
- super(super_hashed_args)
26
- end
27
-
28
- def self.make_handler get_handler, set_handler
29
- handler = lambda do |message|
30
- raise ArgumentError, "message is not a ControlMessage" unless message.is_a?(ControlMessage)
31
-
32
- if message.subtype == GET
33
- return get_handler.call message
34
- elsif message.subtype == SET
35
- return set_handler.call message
36
- else
37
- raise ArgumentError, "message subtype #{message.subtype} is not valid"
38
- end
39
-
40
- end
41
- return handler
42
- end
43
-
44
- def self.make_set_message data
45
- ControlMessage.new :subtype => SET, :data => data
46
- end
47
-
48
- def self.make_get_message
49
- ControlMessage.new :subtype => GET
50
- end
51
- end
52
- end
data/lib/spnet/message.rb DELETED
@@ -1,25 +0,0 @@
1
- require 'hashmake'
2
-
3
- module SPNet
4
- class Message
5
-
6
- include Hashmake::HashMakeable
7
-
8
- CONTROL = :messageTypeControl
9
- COMMAND = :messageTypeCommand
10
-
11
- TYPES = [ CONTROL, COMMAND ]
12
-
13
- HASHED_ARGS_SPECS = [
14
- Hashmake::ArgSpec.new(:reqd => true, :key => :type, :type => Symbol, :validator => ->(a){ TYPES.include?(a) } ),
15
- Hashmake::ArgSpec.new(:reqd => false, :key => :data, :type => Object, :default => nil),
16
- ]
17
-
18
- attr_accessor :data
19
- attr_reader :type
20
-
21
- def initialize hashed_args = {}
22
- hash_make Message::HASHED_ARGS_SPECS, hashed_args
23
- end
24
- end
25
- end
@@ -1,43 +0,0 @@
1
- require 'hashmake'
2
-
3
- module SPNet
4
- class MessageInPort
5
- include Hashmake::HashMakeable
6
-
7
- DEFAULT_VALIDATOR = ->(a){ true }
8
-
9
- ARG_SPECS = [
10
- Hashmake::ArgSpec.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
11
- Hashmake::ArgSpec.new(:reqd => true, :key => :processor, :type => Proc),
12
- Hashmake::ArgSpec.new(:reqd => true, :key => :message_type, :type => Symbol, :validator => ->(a){ Message::TYPES.include?(a) })
13
- ]
14
-
15
- attr_reader :name, :link
16
-
17
- def initialize args
18
- hash_make MessageInPort::ARG_SPECS, args
19
- @queue = []
20
- @link = nil
21
- end
22
-
23
- def recv_message message
24
- raise ArgumentError, "message is not a Message" unless message.is_a?(Message)
25
- if message.type == @message_type
26
- return @processor.call(message)
27
- else
28
- raise ArgumentError, "message.type #{message.type} is not supported on this port"
29
- end
30
-
31
- end
32
-
33
- def clear_link
34
- @link = nil
35
- end
36
-
37
- def set_link link
38
- raise ArgumentError, "link #{link} is not a MessageOutPort" unless link.is_a?(MessageOutPort)
39
- @link = link
40
- end
41
-
42
- end
43
- end
@@ -1,56 +0,0 @@
1
- require 'set'
2
- require 'hashmake'
3
-
4
- module SPNet
5
- class MessageOutPort
6
- include Hashmake::HashMakeable
7
-
8
- ARG_SPECS = [
9
- Hashmake::ArgSpec.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
10
- ]
11
-
12
- attr_reader :name, :links
13
-
14
- def initialize args = {}
15
- hash_make MessageOutPort::ARG_SPECS, args
16
- @links = Set.new
17
- end
18
-
19
- def send_message message
20
- rvs = []
21
- @links.each do |link|
22
- rvs.push link.recv_message message
23
- end
24
- return rvs
25
- end
26
-
27
- def add_link link
28
- raise ArgumentError, "link #{link} is not a MessageInPort" unless link.is_a?(MessageInPort)
29
- raise ArgumentError, "link #{link} is already linked to a MessageInPort" if link.link
30
- @links.add link
31
- link.set_link self
32
- end
33
-
34
- def remove_link link
35
- raise ArgumentError, "link #{link} is not a MessageInPort" unless link.is_a?(MessageInPort)
36
- raise ArgumentError, "@links does not include link #{link}" unless @links.include? link
37
- @links.delete link
38
- link.clear_link
39
- end
40
-
41
- def remove_bad_links
42
- marked_for_removal = []
43
-
44
- @links.each do |link|
45
- bad = (link.link == nil) or (link.link != self)
46
- if bad
47
- marked_for_removal.push link
48
- end
49
- end
50
-
51
- marked_for_removal.each do |link|
52
- @links.delete link
53
- end
54
- end
55
- end
56
- end
@@ -1,60 +0,0 @@
1
- require 'hashmake'
2
-
3
- module SPNet
4
- class SignalInPort
5
- include Hashmake::HashMakeable
6
-
7
- DEFAULT_LIMITS = (-Float::MAX..Float::MAX)
8
-
9
- ARG_SPECS = [
10
- Hashmake::ArgSpec.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
11
- Hashmake::ArgSpec.new(:reqd => false, :key => :limits, :type => Range, :default => DEFAULT_LIMITS)
12
- ]
13
-
14
- attr_reader :name, :limits, :link, :queue
15
-
16
- def make_range_limiter range
17
- return lambda do |input|
18
- if input < range.first
19
- return range.first
20
- elsif input > range.last
21
- return range.last
22
- else
23
- return input
24
- end
25
- end
26
- end
27
-
28
- def initialize args = {}
29
- hash_make SignalInPort::ARG_SPECS, args
30
- @queue = []
31
- @skip_limiting = (@limits == DEFAULT_LIMITS)
32
- @limiter = make_range_limiter @limits
33
- @link = nil
34
- end
35
-
36
- def enqueue_values values
37
- unless @skip_limiting
38
- for i in 0...values.count
39
- values[i] = @limiter.call(values[i])
40
- end
41
- end
42
-
43
- @queue.concat values
44
- end
45
-
46
- def dequeue_values count = @queue.count
47
- raise ArgumentError, "count is greater than @queue.count" if count > @queue.count
48
- @queue.slice!(0...count)
49
- end
50
-
51
- def clear_link
52
- @link = nil
53
- end
54
-
55
- def set_link link
56
- raise ArgumentError, "link #{link} is not a SignalOutPort" unless link.is_a?(SignalOutPort)
57
- @link = link
58
- end
59
- end
60
- end
@@ -1,54 +0,0 @@
1
- require 'set'
2
- require 'hashmake'
3
-
4
- module SPNet
5
- class SignalOutPort
6
- include Hashmake::HashMakeable
7
-
8
- ARG_SPECS = [
9
- Hashmake::ArgSpec.new(:reqd => false, :key => :name, :type => String, :default => "UNNAMED"),
10
- ]
11
-
12
- attr_reader :name, :links
13
-
14
- def initialize args = {}
15
- hash_make SignalOutPort::ARG_SPECS, args
16
- @links = Set.new
17
- end
18
-
19
- def send_values values
20
- @links.each do |link|
21
- link.enqueue_values values
22
- end
23
- end
24
-
25
- def add_link link
26
- raise ArgumentError, "link #{link} is not a SignalInPort" unless link.is_a?(SignalInPort)
27
- raise ArgumentError, "link #{link} is already linked to a SignalOutPort" if link.link
28
- @links.add link
29
- link.set_link self
30
- end
31
-
32
- def remove_link link
33
- raise ArgumentError, "link #{link} is not a SignalInPort" unless link.is_a?(SignalInPort)
34
- raise ArgumentError, "@links does not include link #{link}" unless @links.include? link
35
- @links.delete link
36
- link.clear_link
37
- end
38
-
39
- def remove_bad_links
40
- marked_for_removal = []
41
-
42
- @links.each do |link|
43
- bad = (link.link == nil) or (link.link != self)
44
- if bad
45
- marked_for_removal.push link
46
- end
47
- end
48
-
49
- marked_for_removal.each do |link|
50
- @links.delete link
51
- end
52
- end
53
- end
54
- end
@@ -1,40 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe SPNet::ControlMessage do
4
- describe '.new' do
5
- it 'should set type to Message::CONTROL' do
6
- message = SPNet::ControlMessage.new :subtype => SPNet::ControlMessage::GET
7
- message.type.should eq(SPNet::Message::CONTROL)
8
- end
9
-
10
- it 'should ignore attempt to override type' do
11
- message = SPNet::ControlMessage.new :subtype => SPNet::ControlMessage::GET, :type => :fakeType
12
- message.type.should eq(SPNet::Message::CONTROL)
13
- end
14
-
15
- it 'should allow data to be set' do
16
- message = SPNet::ControlMessage.new :subtype => SPNet::ControlMessage::GET, :data => 17
17
- message.data.should eq(17)
18
- end
19
- end
20
-
21
- describe '.make_set_message' do
22
- it 'should set data' do
23
- message = SPNet::ControlMessage.make_set_message 18
24
- message.data.should eq(18)
25
- end
26
-
27
- it 'should set subtype to ControlMessage::SET' do
28
- message = SPNet::ControlMessage.make_set_message 18
29
- message.subtype.should eq(SPNet::ControlMessage::SET)
30
- end
31
- end
32
-
33
- describe '.make_get_message' do
34
- it 'should set subtype to ControlMessage::GET' do
35
- message = SPNet::ControlMessage.make_get_message
36
- message.subtype.should eq(SPNet::ControlMessage::GET)
37
- end
38
- end
39
-
40
- end
@@ -1,17 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe SPNet::MessageInPort do
4
- describe '#recv_message' do
5
- before :all do
6
- processor = lambda do |message|
7
- return message
8
- end
9
- @port = SPNet::MessageInPort.new :processor => processor, :message_type => SPNet::Message::CONTROL
10
- end
11
-
12
- it 'should pass the given message to the processing callback' do
13
- rv = @port.recv_message SPNet::ControlMessage.make_set_message(5)
14
- rv.data.should eq(5)
15
- end
16
- end
17
- end
data/spec/message_spec.rb DELETED
@@ -1,11 +0,0 @@
1
- require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
-
3
- describe SPNet::Message do
4
- describe '.new' do
5
- it 'should set data and type' do
6
- message = SPNet::Message.new :type => SPNet::Message::CONTROL, :data => 9
7
- message.type.should eq(SPNet::Message::CONTROL)
8
- message.data.should eq(9)
9
- end
10
- end
11
- end