wires 0.1.6 → 0.1.7
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 +4 -4
- data/lib/wires.rb +3 -1
- data/lib/wires/hub.rb +80 -44
- data/lib/wires/time.rb +75 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b10bb4a5abcff971b03e3ed715141508e21059b8
|
4
|
+
data.tar.gz: b2e95646c96b287a988ed2f0608b7b7159bce712
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b92ae83348fd8024b84324ab06d7f73978ffc516738201519e49898dd2ebd8469529792f99dbf7e3a4d1a0d26eb49bcace82e42cf4dabad279490b9d91c8ba70
|
7
|
+
data.tar.gz: 788c6c1ef24826e7b94661f0b5a7db4f30bcd83584e48c41c6438bd0e900f54dd7ad441702629723783c3218b66d2883b3edc0baa5eeab7aa4b1f9a5af8e17fe
|
data/lib/wires.rb
CHANGED
data/lib/wires/hub.rb
CHANGED
@@ -6,68 +6,104 @@ def puts(x) $stdout.puts(x) end
|
|
6
6
|
# An Event Hub. Event/proc associations come in, and the procs
|
7
7
|
# get called in new threads in the order received
|
8
8
|
class Hub
|
9
|
-
|
10
|
-
|
9
|
+
@queue = Queue.new
|
10
|
+
@running = false
|
11
|
+
|
12
|
+
@before_kills = Queue.new
|
13
|
+
@after_kills = Queue.new
|
14
|
+
|
15
|
+
# Operate on the metaclass as a type of singleton pattern
|
16
|
+
class << self
|
11
17
|
|
12
|
-
def
|
18
|
+
def running?; @running; end
|
13
19
|
|
14
20
|
# Start the Hub event loop in a new thread
|
15
|
-
def
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
+
def run
|
22
|
+
if not @running
|
23
|
+
@running = true
|
24
|
+
@thread = Thread.new() {self.send(:run_loop)};
|
25
|
+
at_exit { @thread.join if not $! }
|
26
|
+
end
|
21
27
|
nil end
|
22
28
|
|
23
29
|
# Start the Hub event loop in the current thread
|
24
|
-
def
|
25
|
-
|
30
|
+
def run_in_place()
|
31
|
+
self.send(:run_loop) unless @running
|
26
32
|
nil end
|
27
33
|
|
28
34
|
# Kill the Hub event loop (softly)
|
29
|
-
def
|
35
|
+
def kill();
|
36
|
+
# Call the before kill hooks
|
37
|
+
while not @before_kills.empty?
|
38
|
+
@before_kills.shift.call
|
39
|
+
end
|
40
|
+
# Stop the main event loop
|
41
|
+
@running=false;
|
42
|
+
end
|
43
|
+
|
44
|
+
# Register hook to execute before kill - can call multiple times
|
45
|
+
def before_kill(proc=nil, &block)
|
46
|
+
func = (block or proc)
|
47
|
+
if not func.is_a?(Proc)
|
48
|
+
raise TypeError, "Expected a Proc or code block to execute."
|
49
|
+
end
|
50
|
+
@before_kills << func
|
51
|
+
end
|
52
|
+
|
53
|
+
# Register hook to execute after kill - can call multiple times
|
54
|
+
def after_kill(proc=nil, &block)
|
55
|
+
func = (block or proc)
|
56
|
+
if not func.is_a?(Proc)
|
57
|
+
raise TypeError, "Expected a Proc or code block to execute."
|
58
|
+
end
|
59
|
+
@after_kills << func
|
60
|
+
end
|
30
61
|
|
31
62
|
# Put x in the queue, and block until x is processed
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
63
|
+
def fire(x)
|
64
|
+
@queue << [x, Thread.current]
|
65
|
+
# yield to event loop thread until awoken by it later
|
66
|
+
sleep unless not @running
|
36
67
|
end
|
37
|
-
def
|
68
|
+
def <<(x); fire(x); end
|
38
69
|
|
39
|
-
private
|
70
|
+
private
|
40
71
|
|
41
|
-
def
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
72
|
+
def run_loop
|
73
|
+
@running = true
|
74
|
+
|
75
|
+
while @running
|
76
|
+
if @queue.empty? then sleep(0)
|
77
|
+
else process_item(@queue.shift) end
|
78
|
+
end
|
79
|
+
|
80
|
+
while not @after_kills.empty?
|
81
|
+
@after_kills.shift.call
|
82
|
+
end
|
48
83
|
end
|
49
84
|
|
50
|
-
def
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
end
|
85
|
+
def process_item(x)
|
86
|
+
x, waiting_thread = x
|
87
|
+
string, event, blocking, proc = x
|
88
|
+
Thread.new do
|
89
|
+
begin
|
90
|
+
waiting_thread.wakeup unless blocking
|
91
|
+
proc.call($event = event)
|
92
|
+
waiting_thread.wakeup if blocking
|
93
|
+
|
94
|
+
rescue Interrupt, SystemExit => e
|
95
|
+
@running = false
|
96
|
+
unhandled_exception(e)
|
97
|
+
|
98
|
+
rescue Exception => e
|
99
|
+
unhandled_exception(e)
|
66
100
|
end
|
101
|
+
end
|
67
102
|
end
|
68
103
|
|
69
|
-
def
|
70
|
-
|
71
|
-
|
104
|
+
def unhandled_exception(x)
|
105
|
+
$stderr.puts $!
|
106
|
+
$stderr.puts $@
|
72
107
|
end
|
108
|
+
end
|
73
109
|
end
|
data/lib/wires/time.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
# class StartSchedulerEvent < Event; end
|
4
|
+
|
5
|
+
# # A singleton class to schedule future firing of events
|
6
|
+
# class TimeScheduler
|
7
|
+
# @schedule = Array.new
|
8
|
+
# @schedule_lock = Mutex.new
|
9
|
+
# @grain = 0.2.seconds
|
10
|
+
|
11
|
+
# # Operate on the metaclass as a type of singleton pattern
|
12
|
+
# class << self
|
13
|
+
|
14
|
+
# # Get or set the time grain from outside the class
|
15
|
+
# attr_accessor :grain
|
16
|
+
|
17
|
+
# # Fire an event delayed by time value
|
18
|
+
# def fire(time, event, channel='*')
|
19
|
+
# if not time.is_a? Time
|
20
|
+
# raise TypeError, "Expected #{time.inspect} to be an instance of Time."
|
21
|
+
# end
|
22
|
+
|
23
|
+
# # Under mutex, push the event into the schedule and sort
|
24
|
+
# @schedule_lock.synchronize do
|
25
|
+
# @schedule << [time, event, channel]
|
26
|
+
# @schedule.sort! { |a,b| a[0] <=> b[0] }
|
27
|
+
# end
|
28
|
+
|
29
|
+
# end
|
30
|
+
|
31
|
+
# private
|
32
|
+
|
33
|
+
# def main_loop
|
34
|
+
|
35
|
+
# pending = Array.new
|
36
|
+
|
37
|
+
# while true
|
38
|
+
|
39
|
+
# pending.clear
|
40
|
+
# this_time = Time.now
|
41
|
+
|
42
|
+
# # Under mutex, pull any events that are ready
|
43
|
+
# @schedule_lock.synchronize do
|
44
|
+
# while ((not @schedule.empty?) and (this_time > @schedule[0][0]))
|
45
|
+
# puts 'thing'
|
46
|
+
# pending << @schedule.shift
|
47
|
+
# end
|
48
|
+
# end
|
49
|
+
|
50
|
+
# # Fire pending events
|
51
|
+
# pending.each { |x| Channel(x[2]).fire(x[1]) }
|
52
|
+
|
53
|
+
# # Calculate the time to sleep based on the time left in the "grain"
|
54
|
+
# sleep [@grain-(Time.now-this_time), 0].max
|
55
|
+
|
56
|
+
# end
|
57
|
+
# end
|
58
|
+
|
59
|
+
# end
|
60
|
+
|
61
|
+
# # Use fired event to only start scheduler when Hub is running
|
62
|
+
# # This also gets the scheduler loop its own thread within the Hub's threads
|
63
|
+
# on :start_scheduler, self do; main_loop; end;
|
64
|
+
# Channel(self).fire(:start_scheduler)
|
65
|
+
|
66
|
+
# # Channel(self).fire(:start_scheduler, blocking=true)
|
67
|
+
# end
|
68
|
+
|
69
|
+
# # Reopen the Time class and add the fire method to enable nifty syntax like:
|
70
|
+
# # 32.minutes.from_now.fire :event
|
71
|
+
# class Time
|
72
|
+
# def fire(*args)
|
73
|
+
# TimeScheduler.fire(self, *args)
|
74
|
+
# end
|
75
|
+
# end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: wires
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Joe McIlvain
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-27 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: An asynchronous (threaded) event routing framework in Ruby. Patch your
|
14
14
|
objects together with wires. Inspired by the python 'circuits' framework.
|
@@ -18,6 +18,7 @@ extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
19
19
|
files:
|
20
20
|
- lib/wires.rb
|
21
|
+
- lib/wires/time.rb
|
21
22
|
- lib/wires/hub.rb
|
22
23
|
- lib/wires/events.rb
|
23
24
|
- lib/wires/channels.rb
|