wires 0.2.8 → 0.2.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 +4 -4
- data/lib/wires/hub.rb +49 -29
- data/lib/wires/time.rb +46 -38
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2db21e3f9e121e59a5bb749f91bfc99671408c69
|
4
|
+
data.tar.gz: e05678e737f152a47a9ccd3e7b14214d2ac61f4b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fb026f33a976e5c66d0da73e28bf5ac47deae08b8c1589df176bf70c471c4ea63b8d281777a4416b883258a91e820aeda776db7df0b167441b09b1a5f180c3cf
|
7
|
+
data.tar.gz: 03fbb2d4b977391eecfc75d4f3dfb259dd57b9345bd6c96e050020af2917dac2ad6ced83c89b6ddbb4b12b06b4e720ad611a9e61865c5f00d3b581e975169ce5
|
data/lib/wires/hub.rb
CHANGED
@@ -10,6 +10,8 @@ module Wires
|
|
10
10
|
# Allow user to get/set limit to number of child threads
|
11
11
|
attr_accessor :max_child_threads
|
12
12
|
|
13
|
+
private
|
14
|
+
|
13
15
|
# Make subclasses call class_init
|
14
16
|
def inherited(subcls); subcls.class_init end
|
15
17
|
|
@@ -31,15 +33,20 @@ module Wires
|
|
31
33
|
|
32
34
|
@please_finish_all = false
|
33
35
|
|
34
|
-
@
|
35
|
-
|
36
|
+
@on_neglect = Proc.new do |args|
|
37
|
+
$stderr.puts "#{self} neglected to spawn task: #{args.inspect}"
|
38
|
+
end
|
39
|
+
@on_neglect_done = Proc.new do |args|
|
40
|
+
$stderr.puts "#{self} finally spawned neglected task: #{args.inspect}"
|
41
|
+
end
|
42
|
+
|
43
|
+
at_exit { (sleep 0.05 until dead?) unless $! }
|
36
44
|
|
37
45
|
state_machine_init
|
38
46
|
|
39
47
|
nil end
|
40
48
|
|
41
|
-
|
42
|
-
|
49
|
+
public
|
43
50
|
|
44
51
|
def dead?; state==:dead end
|
45
52
|
def alive?; state==:alive end
|
@@ -68,10 +75,8 @@ module Wires
|
|
68
75
|
# until all child threads are done
|
69
76
|
def kill(*flags)
|
70
77
|
sleep 0 until @spawning_count <= 0
|
71
|
-
|
72
|
-
|
73
|
-
sleep 0 until request_state :dead unless (flags.include? :nonblocking)
|
74
|
-
# end
|
78
|
+
@please_finish_all = (not flags.include? :purge_tasks)
|
79
|
+
sleep 0 until request_state :dead unless (flags.include? :nonblocking)
|
75
80
|
nil end
|
76
81
|
|
77
82
|
# Register hook to execute before run - can call multiple times
|
@@ -94,6 +99,13 @@ module Wires
|
|
94
99
|
@after_kills << [block, retain]
|
95
100
|
nil end
|
96
101
|
|
102
|
+
def on_neglect(&block)
|
103
|
+
@on_neglect=block
|
104
|
+
end
|
105
|
+
def on_neglect_done(&block)
|
106
|
+
@on_neglect_done=block
|
107
|
+
end
|
108
|
+
|
97
109
|
# Spawn a task
|
98
110
|
def spawn(*args) # :args: event, ch_string, proc, blocking
|
99
111
|
@spawning_count_lock.synchronize { @spawning_count += 1 }
|
@@ -136,38 +148,59 @@ module Wires
|
|
136
148
|
|
137
149
|
def purge_neglected
|
138
150
|
@neglected_lock.synchronize do
|
139
|
-
@neglected
|
151
|
+
@neglected.clear
|
152
|
+
end
|
153
|
+
nil end
|
154
|
+
|
155
|
+
def number_neglected
|
156
|
+
@neglected_lock.synchronize do
|
157
|
+
@neglected.size
|
140
158
|
end
|
141
159
|
end
|
142
160
|
|
161
|
+
# Join child threads, one by one, allowing more children to appear
|
162
|
+
def join_children
|
163
|
+
a_thread = Thread.new{nil}
|
164
|
+
while a_thread
|
165
|
+
@child_threads_lock.synchronize do
|
166
|
+
a_thread = @child_threads.shift
|
167
|
+
end
|
168
|
+
a_thread.join if ((a_thread) and (a_thread!=Thread.current))
|
169
|
+
sleep 0 # Yield to other threads
|
170
|
+
end
|
171
|
+
nil end
|
172
|
+
|
143
173
|
private
|
144
174
|
|
145
175
|
# Temporarily neglect a task until resources are available to run it
|
146
176
|
def neglect(*args)
|
147
|
-
$stderr.puts "#{self} neglected to spawn #{args.inspect}"
|
148
177
|
@neglected_lock.synchronize do
|
178
|
+
@on_neglect.call(args)
|
149
179
|
@neglected << args
|
150
180
|
end
|
151
181
|
false end
|
152
182
|
|
153
183
|
# Run a chain of @neglected tasks in place until no more are waiting
|
154
184
|
def spawn_neglected_task_chain
|
155
|
-
|
156
|
-
@neglected_lock.synchronize do
|
185
|
+
args = @neglected_lock.synchronize do
|
157
186
|
return nil if @neglected.empty?
|
158
|
-
|
187
|
+
((@neglected.shift)[0...-1]<<true) # Call with blocking
|
159
188
|
end
|
160
|
-
spawn(*
|
189
|
+
spawn(*args)
|
190
|
+
@on_neglect_done.call(args)
|
161
191
|
spawn_neglected_task_chain
|
162
192
|
nil end
|
163
193
|
|
164
194
|
# Flush @neglected task queue, each in a new thread
|
165
195
|
def spawn_neglected_task_threads
|
166
196
|
until (cease||=false)
|
167
|
-
@neglected_lock.synchronize do
|
197
|
+
args = @neglected_lock.synchronize do
|
168
198
|
break if (cease = @neglected.empty?)
|
169
|
-
|
199
|
+
((@neglected.shift)[0...-1]<<false) # Call without blocking
|
170
200
|
end
|
201
|
+
break if cease
|
202
|
+
spawn(*args)
|
203
|
+
@on_neglect_done.call(args)
|
171
204
|
end
|
172
205
|
nil end
|
173
206
|
|
@@ -185,19 +218,6 @@ module Wires
|
|
185
218
|
end
|
186
219
|
nil end
|
187
220
|
|
188
|
-
# Join child threads, one by one, allowing more children to appear
|
189
|
-
def join_children
|
190
|
-
a_thread = Thread.new{nil}
|
191
|
-
while a_thread
|
192
|
-
@child_threads_lock.synchronize do
|
193
|
-
# flush_queue
|
194
|
-
a_thread = @child_threads.shift
|
195
|
-
end
|
196
|
-
a_thread.join if a_thread
|
197
|
-
sleep 0 # Yield to other threads
|
198
|
-
end
|
199
|
-
nil end
|
200
|
-
|
201
221
|
end
|
202
222
|
|
203
223
|
|
data/lib/wires/time.rb
CHANGED
@@ -37,7 +37,9 @@ module Wires
|
|
37
37
|
|
38
38
|
def active?; @active end
|
39
39
|
def inactive?; not @active end
|
40
|
-
|
40
|
+
|
41
|
+
def ready?(at_time=Time.now); @active and (at_time >= @time) end
|
42
|
+
|
41
43
|
def time_until; (@active ? [(Time.now - @time), 0].max : nil) end
|
42
44
|
|
43
45
|
def cancel; @active = false ;nil end
|
@@ -83,6 +85,8 @@ module Wires
|
|
83
85
|
@schedule_lock = Monitor.new
|
84
86
|
@dont_sleep = false
|
85
87
|
|
88
|
+
@grain = 1.seconds
|
89
|
+
|
86
90
|
# Operate on the metaclass as a type of singleton pattern
|
87
91
|
class << self
|
88
92
|
|
@@ -90,7 +94,6 @@ module Wires
|
|
90
94
|
def add(new_item)
|
91
95
|
expect_type new_item, TimeSchedulerItem
|
92
96
|
schedule_add(new_item)
|
93
|
-
wakeup
|
94
97
|
nil end
|
95
98
|
# Add an event to the schedule using << operator
|
96
99
|
alias_method :<<, :add
|
@@ -98,18 +101,26 @@ module Wires
|
|
98
101
|
# Get a copy of the event schedule from outside the class
|
99
102
|
def list; @schedule.clone end
|
100
103
|
# Clear the event schedule from outside the class
|
101
|
-
def clear;
|
104
|
+
def clear; schedule_clear end
|
102
105
|
|
103
106
|
private
|
104
107
|
|
108
|
+
def schedule_clear
|
109
|
+
@schedule.clear
|
110
|
+
end
|
111
|
+
|
105
112
|
def schedule_reshuffle
|
106
113
|
@schedule.select! {|x| x.active?}
|
107
114
|
@schedule.sort! {|a,b| a.time <=> b.time}
|
108
115
|
nil end
|
109
116
|
|
110
117
|
def schedule_add(new_item)
|
111
|
-
|
112
|
-
|
118
|
+
if new_item.ready?(@next_pass)
|
119
|
+
Thread.new{ new_item.fire_when_ready(blocking:true) }
|
120
|
+
else
|
121
|
+
@schedule << new_item
|
122
|
+
schedule_reshuffle
|
123
|
+
end
|
113
124
|
nil end
|
114
125
|
|
115
126
|
def schedule_concat(other_list)
|
@@ -118,72 +129,69 @@ module Wires
|
|
118
129
|
nil end
|
119
130
|
|
120
131
|
def schedule_pull
|
121
|
-
|
132
|
+
pending_now = Array.new
|
133
|
+
pending_soon = Array.new
|
122
134
|
while ((not @schedule.empty?) and @schedule[0].ready?)
|
123
|
-
|
135
|
+
pending_now << @schedule.shift
|
136
|
+
end
|
137
|
+
while ((not @schedule.empty?) and @schedule[0].ready?(@next_pass))
|
138
|
+
pending_soon << @schedule.shift
|
124
139
|
end
|
125
|
-
[
|
140
|
+
return [pending_now, pending_soon]
|
141
|
+
end
|
142
|
+
|
143
|
+
def schedule_next_pass
|
144
|
+
@next_pass = Time.now+@grain
|
126
145
|
end
|
127
146
|
|
128
147
|
# Put all functions dealing with @schedule under @schedule_lock
|
129
148
|
threadlock :list,
|
130
|
-
:
|
149
|
+
:schedule_clear,
|
131
150
|
:schedule_reshuffle,
|
132
151
|
:schedule_add,
|
133
152
|
:schedule_concat,
|
134
153
|
:schedule_pull,
|
154
|
+
:schedule_next_pass,
|
135
155
|
lock: :@schedule_lock
|
136
156
|
|
137
157
|
def main_loop
|
138
158
|
|
139
|
-
@keepgoing = true
|
159
|
+
# @keepgoing = true
|
140
160
|
pending = Array.new
|
141
161
|
on_deck = nil
|
142
162
|
|
143
163
|
while @keepgoing
|
144
164
|
|
165
|
+
schedule_next_pass
|
166
|
+
|
145
167
|
# Pull, fire, and requeue relevant events
|
146
|
-
|
147
|
-
|
148
|
-
|
168
|
+
pending_now, pending_soon = schedule_pull
|
169
|
+
pending_now.each { |x| x.fire }
|
170
|
+
pending_soon.each{ |x| Thread.new{ x.fire_when_ready(blocking:true) }}
|
171
|
+
# schedule_concat pending_now
|
149
172
|
|
150
|
-
@
|
151
|
-
# Calculate the time to sleep based on next event's time
|
152
|
-
if on_deck
|
153
|
-
sleep on_deck.time_until
|
154
|
-
else # sleep until wakeup if no event is on deck
|
155
|
-
sleep
|
156
|
-
end
|
157
|
-
@sleepzone = false
|
173
|
+
sleep [@next_pass-Time.now, 0].max
|
158
174
|
end
|
159
175
|
|
160
176
|
nil end
|
161
177
|
|
162
|
-
def wakeup
|
163
|
-
sleep 0 until @sleepzone==true
|
164
|
-
sleep 0 until @thread.status=='sleep'
|
165
|
-
@thread.wakeup
|
166
|
-
nil end
|
167
|
-
|
168
178
|
end
|
169
179
|
|
170
|
-
#
|
171
|
-
# This also gets the scheduler loop its own thread within the Hub's threads
|
172
|
-
# on :time_scheduler_start, self do; main_loop; end;
|
173
|
-
# Channel.new(self).fire(:time_scheduler_start)
|
174
|
-
|
175
|
-
# Refire the start event after Hub dies in case it restarts
|
180
|
+
# Start the main loop upon run of Hub
|
176
181
|
Hub.after_run(retain:true) do
|
182
|
+
@keepgoing = true
|
177
183
|
@thread = Thread.new { main_loop }
|
178
184
|
end
|
179
185
|
|
180
186
|
# Stop the main loop upon death of Hub
|
181
|
-
Hub.before_kill(retain:true) do
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
187
|
+
Hub.before_kill(retain:true) do
|
188
|
+
Thread.exclusive do
|
189
|
+
@keepgoing=false
|
190
|
+
@next_pass=Time.now
|
191
|
+
@thread.wakeup
|
192
|
+
end
|
186
193
|
@thread.join
|
194
|
+
schedule_clear
|
187
195
|
end
|
188
196
|
|
189
197
|
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.2.
|
4
|
+
version: 0.2.9
|
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-07-
|
11
|
+
date: 2013-07-14 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|