spnet 0.1.2 → 0.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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