vigilem-core 0.0.9
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.
- 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,45 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
|
3
|
+
require 'vigilem/core/buffer'
|
4
|
+
|
5
|
+
module Vigilem
|
6
|
+
module Core
|
7
|
+
#
|
8
|
+
class DefaultBuffer < ::SimpleDelegator
|
9
|
+
include Buffer
|
10
|
+
|
11
|
+
#
|
12
|
+
# @param [#slice!] type
|
13
|
+
def initialize(type=[])
|
14
|
+
super(type)
|
15
|
+
end
|
16
|
+
|
17
|
+
# like new except type is not optional
|
18
|
+
# and passes through an object that is
|
19
|
+
# already of self type
|
20
|
+
# @param type
|
21
|
+
# @return [DefaultBuffer]
|
22
|
+
def self.wrap(type)
|
23
|
+
if type.is_a? self
|
24
|
+
type
|
25
|
+
else
|
26
|
+
new(type)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# @param other_obj
|
32
|
+
# @return [TrueClass || FalseClass]
|
33
|
+
def ==(other_obj)
|
34
|
+
super(other_obj) ||
|
35
|
+
__getobj__ == other_obj.respond.__getobj__
|
36
|
+
end
|
37
|
+
|
38
|
+
#
|
39
|
+
# @return [String]
|
40
|
+
def inspect
|
41
|
+
"#<#{self.class}:0x#{object_id} #{super}>"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
require 'observer'
|
2
|
+
|
3
|
+
require 'thread_safe'
|
4
|
+
|
5
|
+
require 'vigilem/support/core_ext'
|
6
|
+
|
7
|
+
require 'vigilem/support/obj_space'
|
8
|
+
|
9
|
+
require 'vigilem/support/lazy_simple_delegator'
|
10
|
+
|
11
|
+
require 'vigilem/core/multiplexer'
|
12
|
+
|
13
|
+
module Vigilem
|
14
|
+
module Core
|
15
|
+
# #shift's from input and distributes it to the
|
16
|
+
# observers
|
17
|
+
class Demultiplexer
|
18
|
+
include Observable
|
19
|
+
|
20
|
+
extend Support::ObjSpace
|
21
|
+
|
22
|
+
attr_accessor :input
|
23
|
+
|
24
|
+
alias_method :source, :input
|
25
|
+
alias_method :source=, :input=
|
26
|
+
|
27
|
+
#
|
28
|
+
# @param [Array<Array<observer_object, Hash{@see #add_observer}>>] observers
|
29
|
+
# @param [(Buffer) #slice!] input_source
|
30
|
+
def self.new(input_source=nil, observers=[])
|
31
|
+
obj_register(super(input_source, observers))
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# @param [Array<Array<observer_object, Hash{@see #add_observer}>>] observers
|
36
|
+
# @param [(Buffer) #shift] input_source
|
37
|
+
def initialize(input_source=nil, observers=[])
|
38
|
+
@input = input_source
|
39
|
+
|
40
|
+
add_observers(observers)
|
41
|
+
end
|
42
|
+
|
43
|
+
# the peers without the Delegators
|
44
|
+
# @return [Array]
|
45
|
+
def observers
|
46
|
+
_observers.map {|obj| obj.respond(:peel) || obj }
|
47
|
+
end
|
48
|
+
|
49
|
+
alias_method :outputs, :observers
|
50
|
+
|
51
|
+
#
|
52
|
+
# @return [Array]
|
53
|
+
def _observers
|
54
|
+
(@observer_peers ||= ThreadSafe::Hash.new).keys
|
55
|
+
end
|
56
|
+
|
57
|
+
alias_method :_outputs, :_observers
|
58
|
+
|
59
|
+
# @see Observable#add_observer
|
60
|
+
# @param [Hash] event_opts
|
61
|
+
# @option :func
|
62
|
+
# @option :type [Integer]
|
63
|
+
# @option :types [Array<Integer>]
|
64
|
+
# @option :device_name [Regexp]
|
65
|
+
# @option :device_names [Array<Regexp>]
|
66
|
+
# @option :device [File]
|
67
|
+
# @option :devices [Array<File>]
|
68
|
+
# @return [Array] [event_opts]
|
69
|
+
def add_observer(observer, event_opts={})
|
70
|
+
observer = Support::LazySimpleDelegator.new(observer).use_strict_eql if observer.is_a? Array
|
71
|
+
_observers
|
72
|
+
unless observer.respond_to?(event_opts[:func] ||= :update)
|
73
|
+
raise NoMethodError, "observer does not respond to `#{func.to_s}'"
|
74
|
+
end
|
75
|
+
@observer_peers[observer] = event_opts
|
76
|
+
end
|
77
|
+
|
78
|
+
alias_method :add_output, :add_observer
|
79
|
+
|
80
|
+
# @see Observable#add_observer
|
81
|
+
# @param [Array<Array<observer_object, Hash{@see add_observer}>>]
|
82
|
+
# @return [Array]
|
83
|
+
def add_observers(observers_and_opts)
|
84
|
+
observers_and_opts.map do |(obs, hsh)|
|
85
|
+
add_observer(*[obs, hsh].compact)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
alias_method :add_outputs, :add_observers
|
90
|
+
|
91
|
+
#
|
92
|
+
# @see Object#inspect
|
93
|
+
# @return [String]
|
94
|
+
def inspect
|
95
|
+
if input.is_a? Array # @todo switch from regex
|
96
|
+
super.gsub(/@input=.+?(\s+|>)/, "@input=#<#{input.class}:#{Support::Utils.inspect_id(input)} #{input}>\\1")
|
97
|
+
else
|
98
|
+
super
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
#
|
103
|
+
# @return [Monitor]
|
104
|
+
def semaphore
|
105
|
+
if defined? super
|
106
|
+
super
|
107
|
+
else
|
108
|
+
@semaphore ||= Monitor.new
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
# gets events from input and notifies_observers
|
113
|
+
# @param [Integer] max_number_of_events
|
114
|
+
# @return
|
115
|
+
def demux(max_number_of_events=1)
|
116
|
+
semaphore.synchronize {
|
117
|
+
events = input.shift(max_number_of_events)
|
118
|
+
changed
|
119
|
+
notify_observers(*events)
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
#
|
124
|
+
# @see Observable#notify_observers
|
125
|
+
# @param [Array]
|
126
|
+
# @return [TrueClass || FalseClass]
|
127
|
+
def notify_observers(*events)
|
128
|
+
if defined? @observer_state and @observer_state
|
129
|
+
if defined? @observer_peers
|
130
|
+
@observer_peers.each do |k, event_opts|
|
131
|
+
filtered = self.class.filter_events(events, event_opts)
|
132
|
+
k.send event_opts[:func], filtered unless filtered.empty?
|
133
|
+
end
|
134
|
+
end
|
135
|
+
@observer_state = false
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
alias_method :sweep, :notify_observers
|
140
|
+
alias_method :notify_outputs, :notify_observers
|
141
|
+
|
142
|
+
#
|
143
|
+
# @param [Array] events
|
144
|
+
# @param [Hash{@see #add_observer}] event_opts
|
145
|
+
# @return [Array]
|
146
|
+
def filter_events(events, event_opts)
|
147
|
+
self.class.filter_events(events, event_opts)
|
148
|
+
end
|
149
|
+
|
150
|
+
class << self
|
151
|
+
|
152
|
+
#
|
153
|
+
# @param base
|
154
|
+
# @return
|
155
|
+
def inherited(base)
|
156
|
+
base.extend Support::ObjSpace
|
157
|
+
end
|
158
|
+
|
159
|
+
#
|
160
|
+
# @param [Array<#metadata, #type>] events
|
161
|
+
# @param [Hash{@see #add_observer}] event_opts
|
162
|
+
# @return [Array]
|
163
|
+
def filter_events(events, event_opts)
|
164
|
+
events.select do |event|
|
165
|
+
opts = event_opts.select {|k,v| event_option_names.include? k }
|
166
|
+
if opts.empty?
|
167
|
+
event
|
168
|
+
else
|
169
|
+
opts.all? do |opt,v|
|
170
|
+
opt_vals = [v].flatten
|
171
|
+
case opt.to_s
|
172
|
+
when /^devices?$/
|
173
|
+
opt_vals.any? do |dev|
|
174
|
+
if (src = event.metadata[:source])
|
175
|
+
File.identical?(dev, src)
|
176
|
+
end
|
177
|
+
end
|
178
|
+
when /^device_names?$/
|
179
|
+
opt_vals.any? {|dev_name| event.metadata[:source].respond.name =~ dev_name }
|
180
|
+
when /^types?$/
|
181
|
+
opt_vals.any? {|ev_type| event.type == ev_type }
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
end # else
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
# like first_or_new
|
191
|
+
# @return [Demultiplexer]
|
192
|
+
def acquire(input_source=nil, observers=[], &block)
|
193
|
+
found = all.find(&block)
|
194
|
+
if found
|
195
|
+
found.add_observers(observers)
|
196
|
+
else
|
197
|
+
new(input_source, observers)
|
198
|
+
end
|
199
|
+
end
|
200
|
+
|
201
|
+
#
|
202
|
+
# @return [Hash]
|
203
|
+
def same_source_check
|
204
|
+
all.group_by do |dem|
|
205
|
+
dem.respond(:fileno) || dem
|
206
|
+
end.select {|k, v| v.size > 1 }
|
207
|
+
end
|
208
|
+
|
209
|
+
#
|
210
|
+
# @return [Array<Symbol>]
|
211
|
+
def event_option_names
|
212
|
+
@event_option_names ||= option_names - [:func]
|
213
|
+
end
|
214
|
+
|
215
|
+
#
|
216
|
+
# @return [Array<Symbol>]
|
217
|
+
def option_names
|
218
|
+
@options ||= [:func, :type, :types, :device_name, :device_names, :device, :devices]
|
219
|
+
end
|
220
|
+
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
end
|
225
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'vigilem/core/abstract_device'
|
2
|
+
|
3
|
+
require 'vigilem/core/hooks'
|
4
|
+
|
5
|
+
require 'vigilem/core/system'
|
6
|
+
|
7
|
+
module Vigilem
|
8
|
+
module Core
|
9
|
+
#
|
10
|
+
# hooks for loading the pipeline
|
11
|
+
# errors when no :system_check has passed
|
12
|
+
# @todo more configurable facade so not all methods from
|
13
|
+
# underlying object get through
|
14
|
+
class Device < AbstractDevice
|
15
|
+
|
16
|
+
#
|
17
|
+
# @param [Array] args
|
18
|
+
# @param [Proc] config
|
19
|
+
# @return
|
20
|
+
def self.new(*args, &config)
|
21
|
+
if block_given?
|
22
|
+
(ret = Class.new(self)).instance_eval(&config)
|
23
|
+
ret
|
24
|
+
else
|
25
|
+
super(*args)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Hooks::ConditionalHook.new(:on_os, :type => :system_check) do
|
30
|
+
condition {|name_or_regex| System.check[:os].call(name_or_regex) }
|
31
|
+
end.bind(self)
|
32
|
+
|
33
|
+
Hooks::ConditionalHook.new(:on_input_system, :type => :system_check) do
|
34
|
+
condition {|name_or_regex| System.check[:input_system].call(name_or_regex) }
|
35
|
+
end.bind(self)
|
36
|
+
|
37
|
+
after_init do |dev|
|
38
|
+
raise 'Device not compatible on this system' unless dev.available?
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,156 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
require 'active_support/concern'
|
4
|
+
|
5
|
+
module Vigilem
|
6
|
+
module Core
|
7
|
+
#
|
8
|
+
#
|
9
|
+
module EventHandler
|
10
|
+
|
11
|
+
extend Forwardable
|
12
|
+
|
13
|
+
extend ActiveSupport::Concern
|
14
|
+
|
15
|
+
#
|
16
|
+
#
|
17
|
+
module Utils
|
18
|
+
|
19
|
+
#
|
20
|
+
# @param [#to_s] namespace
|
21
|
+
# @return [String]
|
22
|
+
def snakecase_class_name(namespace)
|
23
|
+
namespace.to_s.split('::').last.snakecase
|
24
|
+
end
|
25
|
+
|
26
|
+
#
|
27
|
+
# @param [Symbol] sym
|
28
|
+
# @return [TrueClass || FalseClass]
|
29
|
+
def respond_to?(sym, include_all=false)
|
30
|
+
on_format?(sym.to_s) || super(sym, include_all)
|
31
|
+
end
|
32
|
+
|
33
|
+
# does the string passed in start with 'on_'
|
34
|
+
# @param [String] str
|
35
|
+
# @return [TrueClass || FalseClass]
|
36
|
+
def on_format?(str)
|
37
|
+
str.start_with?('on_')
|
38
|
+
end
|
39
|
+
|
40
|
+
# converts a "on_String" => :String
|
41
|
+
# @param [String] on_name
|
42
|
+
# @return [Symbol]
|
43
|
+
def type_from_on_format(on_name)
|
44
|
+
on_name.split('on_', 2).last.to_sym
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
include Utils
|
49
|
+
extend Utils
|
50
|
+
|
51
|
+
module ClassMethods
|
52
|
+
|
53
|
+
include Utils
|
54
|
+
|
55
|
+
# @todo Fuzzy is_a? Hash key lookup
|
56
|
+
# @return [Hash]
|
57
|
+
def type_handles
|
58
|
+
@type_handles ||= {}
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# sets the default_handler, if called without a block, just
|
63
|
+
# assigns the default handler to a "default"
|
64
|
+
# @param [Proc] block
|
65
|
+
# @return [Proc]
|
66
|
+
def default_handler(&block)
|
67
|
+
type_handles.default = (block || lambda {|*args, &block| })
|
68
|
+
end
|
69
|
+
|
70
|
+
# @todo module_function
|
71
|
+
# configures how this event handler handles an event
|
72
|
+
# @param type
|
73
|
+
# @return [Proc] the block given/registered
|
74
|
+
def on(type, opts={}, &block)
|
75
|
+
type_name = snakecase_class_name(type)
|
76
|
+
on_method = send(:_define_register, type, type_name)
|
77
|
+
type_handles[type] = send(:_define_handler, type_name, &block)
|
78
|
+
on_method.call(&block)
|
79
|
+
end
|
80
|
+
|
81
|
+
alias_method :register_handle, :on
|
82
|
+
|
83
|
+
private
|
84
|
+
|
85
|
+
# defines `on_#{event_type}'
|
86
|
+
# @param type
|
87
|
+
# @param [String] type_name
|
88
|
+
# @param [Proc] block
|
89
|
+
# @return [Method]
|
90
|
+
def _define_register(type, type_name)
|
91
|
+
define_singleton_method(on_method_name = :"on_#{type_name}") {|opts={}, &blk| type_handles[type] = blk }
|
92
|
+
define_method(on_method_name) {|opts={}, &blk| self.class.send(on_method_name, opts, &blk) }
|
93
|
+
method(on_method_name)
|
94
|
+
end
|
95
|
+
|
96
|
+
# defines `handle_#{event_type}'
|
97
|
+
# @param [String] type
|
98
|
+
# @param [Proc] block
|
99
|
+
# @return [Proc]
|
100
|
+
def _define_handler(type_name, &block)
|
101
|
+
define_method(handler_name = :"handle_#{type_name}", &block)
|
102
|
+
block
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
106
|
+
|
107
|
+
#
|
108
|
+
# @return [Hash]
|
109
|
+
def type_handles
|
110
|
+
self.class.type_handles
|
111
|
+
end
|
112
|
+
|
113
|
+
# to trigger the handling, either use handle(event, opts={}) or handle_#{type}
|
114
|
+
# configures how this event handler handles an event
|
115
|
+
# @param [#to_s] type
|
116
|
+
# @return [Proc] the block given/registered
|
117
|
+
def on(type, &block)
|
118
|
+
define_singleton_method(on_method_name = :"on_#{class_name = snakecase_class_name(type)}") {|&blk| type_handles[type] = blk }
|
119
|
+
ret = send on_method_name, &block
|
120
|
+
define_singleton_method(handler_name = :"handle_#{class_name}", &type_handles[type])
|
121
|
+
ret
|
122
|
+
end
|
123
|
+
alias_method :register_handle, :on
|
124
|
+
|
125
|
+
#
|
126
|
+
# @param event, the event to handle
|
127
|
+
# @param [Array]
|
128
|
+
# @return results of the Proc registered to the type_handless
|
129
|
+
def handle(event, *args, &block)
|
130
|
+
if handler = type_handles[event.class]
|
131
|
+
handler.call(event, *args, &block)
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
#
|
136
|
+
# @param event, the event to handle
|
137
|
+
# @param [Array]
|
138
|
+
# @return results of the Proc registered to the type_handless
|
139
|
+
def handle!(event, *args, &block)
|
140
|
+
if ret = handle(event, *args, &block)
|
141
|
+
ret
|
142
|
+
else
|
143
|
+
raise NotImplementedError, "No handler found for #{key.class}:#{key},#{block} and no default handler set"
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
#
|
148
|
+
# @param [Proc]
|
149
|
+
# @return
|
150
|
+
def default_handler(&block)
|
151
|
+
self.class.default_handler(&block)
|
152
|
+
end
|
153
|
+
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|