vigilem-core 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/lib/vigilem/core.rb +9 -0
- data/lib/vigilem/core/abstract_device.rb +97 -0
- data/lib/vigilem/core/adapters.rb +2 -0
- data/lib/vigilem/core/adapters/adapter.rb +57 -0
- data/lib/vigilem/core/adapters/basic_adapter.rb +43 -0
- data/lib/vigilem/core/adapters/buffered_adapter.rb +28 -0
- data/lib/vigilem/core/buffer.rb +151 -0
- data/lib/vigilem/core/buffer_handler.rb +95 -0
- data/lib/vigilem/core/default_buffer.rb +45 -0
- data/lib/vigilem/core/demultiplexer.rb +225 -0
- data/lib/vigilem/core/device.rb +43 -0
- data/lib/vigilem/core/event_handler.rb +156 -0
- data/lib/vigilem/core/eventable.rb +80 -0
- data/lib/vigilem/core/hooks.rb +36 -0
- data/lib/vigilem/core/hooks/callback.rb +66 -0
- data/lib/vigilem/core/hooks/callback_proc.rb +25 -0
- data/lib/vigilem/core/hooks/conditional_hook.rb +62 -0
- data/lib/vigilem/core/hooks/hook.rb +193 -0
- data/lib/vigilem/core/hooks/inheritable.rb +24 -0
- data/lib/vigilem/core/hooks/meta_callback.rb +53 -0
- data/lib/vigilem/core/hooks/utils.rb +23 -0
- data/lib/vigilem/core/hub.rb +50 -0
- data/lib/vigilem/core/input_system_handler.rb +55 -0
- data/lib/vigilem/core/lockable_pipeline_component.rb +30 -0
- data/lib/vigilem/core/multiplexer.rb +168 -0
- data/lib/vigilem/core/pipeline.rb +68 -0
- data/lib/vigilem/core/stat.rb +121 -0
- data/lib/vigilem/core/system.rb +9 -0
- data/lib/vigilem/core/system/check.rb +33 -0
- data/lib/vigilem/core/transfer_agent.rb +67 -0
- data/lib/vigilem/core/version.rb +5 -0
- data/spec/bug_notes.txt +12 -0
- data/spec/given_helper.rb +12 -0
- data/spec/spec_helper.rb +7 -0
- data/spec/vigilem/core/abstract_device_spec.rb +103 -0
- data/spec/vigilem/core/adapters/adapter_spec.rb +28 -0
- data/spec/vigilem/core/adapters/basic_adapter_spec.rb +53 -0
- data/spec/vigilem/core/adapters/buffered_adapter_spec.rb +16 -0
- data/spec/vigilem/core/buffer_handler_spec.rb +51 -0
- data/spec/vigilem/core/buffer_spec.rb +236 -0
- data/spec/vigilem/core/default_buffer_spec.rb +17 -0
- data/spec/vigilem/core/demultiplexer_spec.rb +166 -0
- data/spec/vigilem/core/device_spec.rb +62 -0
- data/spec/vigilem/core/event_handler_spec.rb +134 -0
- data/spec/vigilem/core/hooks/callback_proc_spec.rb +66 -0
- data/spec/vigilem/core/hooks/hook_spec.rb +230 -0
- data/spec/vigilem/core/hooks/inheritable_spec.rb +19 -0
- data/spec/vigilem/core/hooks/meta_callback_spec.rb +69 -0
- data/spec/vigilem/core/hooks/utils_spec.rb +25 -0
- data/spec/vigilem/core/hooks_spec.rb +50 -0
- data/spec/vigilem/core/hub_spec.rb +51 -0
- data/spec/vigilem/core/input_system_handler_spec.rb +33 -0
- data/spec/vigilem/core/lockable_pipeline_component_spec.rb +19 -0
- data/spec/vigilem/core/multiplexer_spec.rb +113 -0
- data/spec/vigilem/core/pipeline_spec.rb +5 -0
- data/spec/vigilem/core/stat_spec.rb +63 -0
- data/spec/vigilem/core/system/check_spec.rb +24 -0
- data/spec/vigilem/core/system_spec.rb +29 -0
- data/spec/vigilem/core/transfer_agent_spec.rb +80 -0
- metadata +273 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'vigilem/support/core_ext'
|
2
|
+
|
3
|
+
module Vigilem
|
4
|
+
module Core
|
5
|
+
module Hooks
|
6
|
+
#
|
7
|
+
module Inheritable
|
8
|
+
|
9
|
+
#
|
10
|
+
# @param base
|
11
|
+
def inherited(base)
|
12
|
+
base.extend Inheritable
|
13
|
+
end
|
14
|
+
|
15
|
+
#
|
16
|
+
# @return [Array]
|
17
|
+
def hooks
|
18
|
+
@hooks ||= (self.superclass.respond(:hooks) || []).select(&:inheritable?)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
module Vigilem::Core::Hooks
|
4
|
+
# @todo better name?
|
5
|
+
# CallbackProc that remebers if it has been ran/evaluated/called
|
6
|
+
class MetaCallback < DelegateClass(CallbackProc)
|
7
|
+
|
8
|
+
#
|
9
|
+
# @param [CallbackProc] cbp a CallbackProc
|
10
|
+
# to be converted to a MetaCallback
|
11
|
+
# @param [Proc] block a Proc to be converted to a MetaCallback
|
12
|
+
def initialize(cbp=nil, &block)
|
13
|
+
self.ran = false
|
14
|
+
super(cbp || CallbackProc.new(&block))
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# @param context the context which to evaluate under
|
19
|
+
# @param [Array] args arguments to be passed to the proc
|
20
|
+
# @param [Proc] block Proc to be passed to the proc
|
21
|
+
# @return the result of the
|
22
|
+
def evaluate(context, *args, &block)
|
23
|
+
self.ran = true
|
24
|
+
super(context, *args, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
alias_method :[], :evaluate
|
28
|
+
|
29
|
+
#
|
30
|
+
# @param [Array] args arguments to be passed to the proc
|
31
|
+
# @param [Proc] block Proc to be passed to the proc
|
32
|
+
# @return the result of the proc
|
33
|
+
def call(*args, &block)
|
34
|
+
self.ran = true
|
35
|
+
super(*args, &block)
|
36
|
+
end
|
37
|
+
|
38
|
+
# whether or not this proc ran
|
39
|
+
# @return [TrueClass || FalseClass]
|
40
|
+
def ran?
|
41
|
+
@ran
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
#
|
47
|
+
# @param [TrueClass || FalseClass] status
|
48
|
+
# @return @ran
|
49
|
+
def ran=(status)
|
50
|
+
@ran = status
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'vigilem/support/utils'
|
2
|
+
|
3
|
+
module Vigilem
|
4
|
+
module Core::Hooks
|
5
|
+
#
|
6
|
+
# utils for the Hooks
|
7
|
+
module Utils
|
8
|
+
|
9
|
+
include Support::KernelUtils
|
10
|
+
|
11
|
+
#
|
12
|
+
# if context of callback is a subclass of this context
|
13
|
+
# @param context
|
14
|
+
# @param callback
|
15
|
+
# @return [FalseClass || TrueClass]
|
16
|
+
def callback_is_in_subclass?(context, callback)
|
17
|
+
get_class(callback.binding.eval('self')) < get_class(context)
|
18
|
+
end
|
19
|
+
|
20
|
+
extend self
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'vigilem/support/obj_space'
|
2
|
+
|
3
|
+
module Vigilem
|
4
|
+
module Core
|
5
|
+
# copies events or messages from the system to all the
|
6
|
+
# attached buffers except the link, much like a network hub
|
7
|
+
class Hub
|
8
|
+
|
9
|
+
attr_reader :buffers, :group_id
|
10
|
+
|
11
|
+
# @param group
|
12
|
+
def initialize(group)
|
13
|
+
@group_id = group
|
14
|
+
@buffers = []
|
15
|
+
end
|
16
|
+
|
17
|
+
#
|
18
|
+
# @param [EventBuffer] buffer that will receive events from the hub
|
19
|
+
# @return self is expected like array
|
20
|
+
def add_buffer(buffer)
|
21
|
+
@buffers << buffer
|
22
|
+
self
|
23
|
+
end
|
24
|
+
|
25
|
+
alias_method :<<, :add_buffer
|
26
|
+
|
27
|
+
#
|
28
|
+
# @param [Array] msgs the messages to push out
|
29
|
+
# @return [Array] the buffers that got updated
|
30
|
+
def demux(buff, *msgs)
|
31
|
+
buffers.except(buff).select {|buffer| buffer.concat(msgs) unless msgs.empty? }
|
32
|
+
end
|
33
|
+
|
34
|
+
extend Support::ObjSpace
|
35
|
+
|
36
|
+
class << self
|
37
|
+
|
38
|
+
#
|
39
|
+
# finds a hub based on a group identifier, if no Hub is found
|
40
|
+
# a new one is returned
|
41
|
+
# @param link the link registered for a hub
|
42
|
+
# @return [Hub] the hub for passed in link
|
43
|
+
def aquire(grp_id)
|
44
|
+
all.find {|hub| hub.group_id == grp_id } || obj_register(new(grp_id))
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'vigilem/support/core_ext'
|
4
|
+
|
5
|
+
require 'vigilem/core/lockable_pipeline_component'
|
6
|
+
|
7
|
+
require 'vigilem/core/adapters/basic_adapter'
|
8
|
+
|
9
|
+
require 'vigilem/core/buffer_handler'
|
10
|
+
|
11
|
+
require 'vigilem/core/transfer_agent'
|
12
|
+
|
13
|
+
module Vigilem
|
14
|
+
module Core
|
15
|
+
#
|
16
|
+
# methods to hand the lower level bindings
|
17
|
+
module InputSystemHandler
|
18
|
+
|
19
|
+
include BufferHandler
|
20
|
+
|
21
|
+
include Adapters::BasicAdapter
|
22
|
+
|
23
|
+
include LockablePipelineComponent
|
24
|
+
|
25
|
+
extend Support::ObjSpace
|
26
|
+
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
#
|
30
|
+
# @param buffer_type
|
31
|
+
# @return
|
32
|
+
def initialize_input_system_handler(buffer_type=[])
|
33
|
+
ret = initialize_buffer_handler(buffer_type)
|
34
|
+
InputSystemHandler.obj_register(self)
|
35
|
+
self.class.obj_register(self)
|
36
|
+
ret
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
#
|
41
|
+
module ClassMethods
|
42
|
+
include Support::ObjSpace
|
43
|
+
|
44
|
+
include Forwardable
|
45
|
+
|
46
|
+
#
|
47
|
+
#
|
48
|
+
def self.extended(base)
|
49
|
+
base.extend Support::ObjSpace
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'vigilem/support/core_ext'
|
2
|
+
|
3
|
+
module Vigilem
|
4
|
+
module Core
|
5
|
+
#
|
6
|
+
module LockablePipelineComponent
|
7
|
+
|
8
|
+
#
|
9
|
+
# name collision with demultiplexer and bufferhandler
|
10
|
+
def semaphore
|
11
|
+
@semaphore ||= (semaphore! || Monitor.new)
|
12
|
+
end
|
13
|
+
|
14
|
+
#
|
15
|
+
# checks #source component for #semaphore without memoization
|
16
|
+
def semaphore!
|
17
|
+
self.respond.source.respond.semaphore
|
18
|
+
end
|
19
|
+
|
20
|
+
#
|
21
|
+
#
|
22
|
+
def synchronize
|
23
|
+
semaphore.synchronize do
|
24
|
+
yield
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'active_support/concern'
|
2
|
+
|
3
|
+
require 'vigilem/support/obj_space'
|
4
|
+
|
5
|
+
require 'vigilem/support/utils'
|
6
|
+
|
7
|
+
module Vigilem
|
8
|
+
module Core
|
9
|
+
#
|
10
|
+
#
|
11
|
+
module Multiplexer
|
12
|
+
|
13
|
+
extend Support::ObjSpace
|
14
|
+
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
|
17
|
+
attr_writer :inputs
|
18
|
+
|
19
|
+
attr_accessor :out
|
20
|
+
|
21
|
+
alias_method :output, :out
|
22
|
+
alias_method :output=, :out=
|
23
|
+
|
24
|
+
#
|
25
|
+
# @param [Array<IO || Array>] in_ios_or_arrays
|
26
|
+
# @param [Array<#<< || #concat>] out
|
27
|
+
# @return
|
28
|
+
def initialize_multiplexer(in_ios_or_arrays, out=nil)
|
29
|
+
@inputs = in_ios_or_arrays
|
30
|
+
|
31
|
+
@out = out
|
32
|
+
self.class.obj_register(self)
|
33
|
+
multiplexers = ::Vigilem::Core::Multiplexer.all
|
34
|
+
if (ties = multiplexers.flat_map {|muxer| self.intersect muxer }).any?
|
35
|
+
raise NotImplemented, "Multiplexers cannot share the same inputs `#{ties.inspect}'"
|
36
|
+
end
|
37
|
+
multiplexers << self
|
38
|
+
end
|
39
|
+
|
40
|
+
# @todo change name to select?
|
41
|
+
# @return [Array<IO> || NilClass] objects ready to be read, or nil
|
42
|
+
# if nothing is to be read
|
43
|
+
def ready?
|
44
|
+
if not (ios = inputs.select {|io| io.respond_to? :to_io }).empty?
|
45
|
+
@ready, others = IO.select(ios, nil, nil, 0)
|
46
|
+
end
|
47
|
+
@ready ||= []
|
48
|
+
@ready += inputs.select {|ary| ary.respond_to?(:empty?) and ary.empty? }
|
49
|
+
end
|
50
|
+
|
51
|
+
#
|
52
|
+
# @raise [ArgumentError]
|
53
|
+
# @return [Array]
|
54
|
+
def __sweep__(len)
|
55
|
+
recursive_check(RuntimeError)
|
56
|
+
sweep(len)
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# @param [Integer] num
|
61
|
+
# @return
|
62
|
+
def sweep(num)
|
63
|
+
raise NotImplemented, "#sweep method not defined on `#{self}' needs to be overriden"
|
64
|
+
end
|
65
|
+
|
66
|
+
#
|
67
|
+
# pushes the converted array from #sweep to #out
|
68
|
+
# @param [Integer] len
|
69
|
+
# @return [Array]
|
70
|
+
def mux(len)
|
71
|
+
ary = __sweep__(len)
|
72
|
+
if out.respond_to? :concat
|
73
|
+
out.concat(ary)
|
74
|
+
elsif out.respond_to? :<<
|
75
|
+
ary.each {|item| out << item }
|
76
|
+
else
|
77
|
+
raise TypeError, "`#{self}'#out is `#{self.out.inspect}' and does not respond to #concat or #<<"
|
78
|
+
end
|
79
|
+
out.flush if out.respond_to? :flush
|
80
|
+
ary
|
81
|
+
end
|
82
|
+
|
83
|
+
#
|
84
|
+
# @return [Array]
|
85
|
+
def inputs
|
86
|
+
@inputs ||= []
|
87
|
+
end
|
88
|
+
|
89
|
+
# adds a inputs and runs a uniq
|
90
|
+
# @param [Array<IO || Array>] added_inputs
|
91
|
+
# @return [Array<IO || Array>]
|
92
|
+
def add_inputs(*added_inputs)
|
93
|
+
if not added_inputs.empty?
|
94
|
+
(self.inputs += added_inputs).uniq! {|obj| obj.object_id }
|
95
|
+
recursive_check
|
96
|
+
end
|
97
|
+
self.inputs
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
#
|
102
|
+
module ClassMethods
|
103
|
+
|
104
|
+
include Support::ObjSpace
|
105
|
+
|
106
|
+
#
|
107
|
+
# @param [Module] base
|
108
|
+
def self.extended(base)
|
109
|
+
base.extend Support::ObjSpace
|
110
|
+
end
|
111
|
+
|
112
|
+
end
|
113
|
+
|
114
|
+
extend ClassMethods
|
115
|
+
|
116
|
+
#
|
117
|
+
# @see Object#inspect
|
118
|
+
# @return [String]
|
119
|
+
def inspect
|
120
|
+
if out.is_a? Array # @todo switch from regex
|
121
|
+
updated_out = super.gsub(/@out=.+?(\s+|>)/, "@out=#<#{out.class}:#{Support::Utils.inspect_id(out)} #{out}>\\1")
|
122
|
+
|
123
|
+
if inputs.any? {|inp| inp.is_a? Array }
|
124
|
+
str_ary_bdy = inputs.map do |inp|
|
125
|
+
if inp.is_a?(Array)
|
126
|
+
"#<#{inp.class}:#{Support::Utils.inspect_id(inp)} #{inp}>"
|
127
|
+
else
|
128
|
+
inp
|
129
|
+
end
|
130
|
+
end.join(', ')
|
131
|
+
updated_out.gsub(/@inputs=.+?(\s+|>)/, "@inputs=[#{str_ary_bdy}]\\1")
|
132
|
+
end || updated_out
|
133
|
+
|
134
|
+
else
|
135
|
+
super
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
# compares the inputs to the list or multiplexer given
|
140
|
+
# @param [Multiplexer || Array<IO> || Array<Array<>>] other_mux_or_ios_or_arrays
|
141
|
+
# @return [Array]
|
142
|
+
def intersect(*other_mux_or_ios_or_arrays)
|
143
|
+
ios, non_fileno = self.inputs.partition {|inpt| inpt.respond_to?(:fileno) }
|
144
|
+
ios_fn = ios.map(&:fileno)
|
145
|
+
|
146
|
+
non_fileno.map!(&:object_id)
|
147
|
+
|
148
|
+
ary = other_mux_or_ios_or_arrays.respond_to?(:inputs) ? other_mux_or_ios_or_arrays.inputs : other_mux_or_ios_or_arrays
|
149
|
+
ary.select do |inp|
|
150
|
+
if inp.respond_to? :fileno
|
151
|
+
ios_fn.include? inp.fileno
|
152
|
+
else
|
153
|
+
non_fileno.include? inp.object_id #default compares by #hash
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
private
|
159
|
+
# checks to make sure that an input doesn't match an output thus causing
|
160
|
+
# a recursive loop, raises an error if found
|
161
|
+
# @raise [ArgumentError]
|
162
|
+
# @return
|
163
|
+
def recursive_check(arg_type=ArgumentError)
|
164
|
+
raise arg_type, "Recursive multiplexer `#{self}' has `#{out}' as an input and output" unless intersect(out).empty?
|
165
|
+
end
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Vigilem
|
2
|
+
module Core
|
3
|
+
#
|
4
|
+
# observer of components and thier connections
|
5
|
+
# the catch is that input_systems don;t have an entry point
|
6
|
+
# for determining thier source
|
7
|
+
class Pipeline
|
8
|
+
attr_reader :device
|
9
|
+
|
10
|
+
#
|
11
|
+
# @param [#link] device most likely a Core::Device
|
12
|
+
def initialize(device)
|
13
|
+
@device = device
|
14
|
+
rebuild
|
15
|
+
end
|
16
|
+
|
17
|
+
extend Support::ObjSpace
|
18
|
+
|
19
|
+
# get the next item that #source
|
20
|
+
# is pointing to
|
21
|
+
# @return
|
22
|
+
def succ
|
23
|
+
@iter ||= device
|
24
|
+
@iter.respond(:source)
|
25
|
+
end
|
26
|
+
|
27
|
+
# the start of the pipeline
|
28
|
+
# @return [#source]
|
29
|
+
def reset_iter
|
30
|
+
@iter = device
|
31
|
+
end
|
32
|
+
|
33
|
+
# rebuilds the cache
|
34
|
+
# @return [Array]
|
35
|
+
def rebuild
|
36
|
+
ary = [device]
|
37
|
+
while current = succ
|
38
|
+
ary << current
|
39
|
+
end
|
40
|
+
reset_iter
|
41
|
+
cache = ary
|
42
|
+
end
|
43
|
+
|
44
|
+
# updates the status
|
45
|
+
# called when a component changes it's sauce
|
46
|
+
# @return [TrueClass]
|
47
|
+
def update
|
48
|
+
@changed = true
|
49
|
+
end
|
50
|
+
|
51
|
+
# checks whether or not this item changed
|
52
|
+
# @return [TrueClass || FalseClass]
|
53
|
+
def changed?
|
54
|
+
@changed ||= false
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [Array] all the components in the pipeline
|
58
|
+
def to_a
|
59
|
+
changed? ? rebuild : cache
|
60
|
+
end
|
61
|
+
|
62
|
+
alias_method :to_ary, :to_a
|
63
|
+
|
64
|
+
private
|
65
|
+
attr_accessor :cache
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|