lifeguard 0.2.1 → 0.3.0
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/.travis.yml +3 -2
- data/lib/lifeguard/infinite_threadpool.rb +17 -7
- data/lib/lifeguard/reaper.rb +0 -1
- data/lib/lifeguard/threadpool.rb +13 -51
- data/lib/lifeguard/version.rb +1 -1
- data/spec/lifeguard/threadpool_spec.rb +6 -4
- metadata +4 -4
data/.travis.yml
CHANGED
@@ -14,16 +14,26 @@ module Lifeguard
|
|
14
14
|
return false if @shutdown
|
15
15
|
|
16
16
|
if busy?
|
17
|
+
job_mutex = ::Mutex.new
|
18
|
+
job_condition = ::ConditionVariable.new
|
17
19
|
# Account for "weird" exceptions like Java Exceptions or higher up the chain
|
18
20
|
# than what `rescue nil` will capture
|
19
|
-
|
20
|
-
::Thread.
|
21
|
-
|
22
|
-
|
23
|
-
|
21
|
+
job_mutex.synchronize do
|
22
|
+
new_thread = ::Thread.new(block, args) do |callable, call_args|
|
23
|
+
job_mutex.synchronize do
|
24
|
+
begin
|
25
|
+
::Thread.current[:__start_time_in_seconds__] = Time.now.to_i
|
26
|
+
::Thread.current.abort_on_exception = false
|
27
|
+
|
28
|
+
callable.call(*call_args)
|
29
|
+
ensure
|
30
|
+
job_condition.signal
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
job_condition.wait(job_mutex)
|
24
36
|
end
|
25
|
-
|
26
|
-
::Thread.pass while new_thread.alive?
|
27
37
|
else
|
28
38
|
super(*args, &block)
|
29
39
|
end
|
data/lib/lifeguard/reaper.rb
CHANGED
data/lib/lifeguard/threadpool.rb
CHANGED
@@ -24,7 +24,7 @@ module Lifeguard
|
|
24
24
|
#
|
25
25
|
@timeout = opts[:timeout]
|
26
26
|
@mutex = ::Mutex.new
|
27
|
-
@busy_threads =
|
27
|
+
@busy_threads = ThreadGroup.new
|
28
28
|
|
29
29
|
restart_reaper_unless_alive
|
30
30
|
end
|
@@ -37,20 +37,12 @@ module Lifeguard
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def busy_size
|
40
|
-
@busy_threads.size
|
40
|
+
@busy_threads.list.size
|
41
41
|
end
|
42
42
|
|
43
43
|
def kill!
|
44
44
|
@mutex.synchronize do
|
45
|
-
|
46
|
-
@busy_threads.each { |busy_thread| busy_thread.kill }
|
47
|
-
prune_busy_threads_without_mutex
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
def on_thread_exit(thread)
|
52
|
-
@mutex.synchronize do
|
53
|
-
@busy_threads.delete(thread)
|
45
|
+
@busy_threads.list.each { |busy_thread| busy_thread.kill }
|
54
46
|
end
|
55
47
|
end
|
56
48
|
|
@@ -63,50 +55,26 @@ module Lifeguard
|
|
63
55
|
end
|
64
56
|
|
65
57
|
@mutex.synchronize do
|
66
|
-
prune_busy_threads_without_mutex
|
67
|
-
|
68
58
|
if busy_size < pool_size
|
69
59
|
queued_the_work = true
|
70
60
|
|
71
|
-
@busy_threads
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
ensure
|
77
|
-
parent.on_thread_exit(::Thread.current)
|
78
|
-
end
|
79
|
-
end
|
61
|
+
@busy_threads.add ::Thread.new(block, args, self) { |callable, call_args, parent|
|
62
|
+
::Thread.current.abort_on_exception = false
|
63
|
+
::Thread.current[:__start_time_in_seconds__] = Time.now.to_i
|
64
|
+
callable.call(*call_args) # should we check the args? pass args?
|
65
|
+
}
|
80
66
|
end
|
81
67
|
|
82
|
-
prune_busy_threads_without_mutex
|
83
68
|
queued_the_work
|
84
69
|
end
|
85
70
|
end
|
86
71
|
|
87
|
-
def
|
88
|
-
|
89
|
-
prune_busy_threads_without_mutex
|
90
|
-
end
|
91
|
-
end
|
72
|
+
def shutdown(shutdown_timeout = 3)
|
73
|
+
kill_at = Time.now.to_f + shutdown_timeout
|
92
74
|
|
93
|
-
def shutdown(shutdown_timeout = 0)
|
94
75
|
@mutex.synchronize do
|
95
|
-
|
96
|
-
|
97
|
-
if @busy_threads.size > 0
|
98
|
-
# Cut the shutdown_timeout by 10 and prune while things finish before the kill
|
99
|
-
(shutdown_timeout/10).times do
|
100
|
-
sleep (shutdown_timeout / 10.0)
|
101
|
-
prune_busy_threads_without_mutex
|
102
|
-
break if busy_size == 0
|
103
|
-
end
|
104
|
-
|
105
|
-
sleep(shutdown_timeout/10)
|
106
|
-
@busy_threads.each { |busy_thread| busy_thread.kill }
|
107
|
-
end
|
108
|
-
|
109
|
-
prune_busy_threads_without_mutex
|
76
|
+
sleep 0.01 while busy_size > 0 && Time.now.to_f < kill_at
|
77
|
+
@busy_threads.list.each { |busy_thread| busy_thread.kill }
|
110
78
|
end
|
111
79
|
end
|
112
80
|
|
@@ -114,13 +82,11 @@ module Lifeguard
|
|
114
82
|
return unless timeout?
|
115
83
|
|
116
84
|
@mutex.synchronize do
|
117
|
-
@busy_threads.each do |busy_thread|
|
85
|
+
@busy_threads.list.each do |busy_thread|
|
118
86
|
if (Time.now.to_i - busy_thread[:__start_time_in_seconds__] > @timeout)
|
119
87
|
busy_thread.kill
|
120
88
|
end
|
121
89
|
end
|
122
|
-
|
123
|
-
prune_busy_threads_without_mutex
|
124
90
|
end
|
125
91
|
end
|
126
92
|
|
@@ -133,10 +99,6 @@ module Lifeguard
|
|
133
99
|
##
|
134
100
|
# Private Instance Methods
|
135
101
|
#
|
136
|
-
def prune_busy_threads_without_mutex
|
137
|
-
@busy_threads.select!(&:alive?)
|
138
|
-
end
|
139
|
-
|
140
102
|
def restart_reaper_unless_alive
|
141
103
|
return if @reaper && @reaper.alive?
|
142
104
|
|
data/lib/lifeguard/version.rb
CHANGED
@@ -45,14 +45,17 @@ describe ::Lifeguard::Threadpool do
|
|
45
45
|
end
|
46
46
|
|
47
47
|
it "uses the reaper to timeout threads that are all wiley" do
|
48
|
+
expected = false
|
48
49
|
threadpool = described_class.new(:timeout => 1, :reaping_interval => 1)
|
49
50
|
threadpool.async do
|
50
|
-
sleep(
|
51
|
+
sleep(3)
|
52
|
+
expected = true
|
51
53
|
end
|
52
54
|
|
53
55
|
threadpool.busy_size.should eq(1)
|
54
56
|
sleep(4)
|
55
57
|
threadpool.busy_size.should eq(0)
|
58
|
+
expected.should be(false)
|
56
59
|
end
|
57
60
|
end
|
58
61
|
|
@@ -78,13 +81,12 @@ describe ::Lifeguard::Threadpool do
|
|
78
81
|
|
79
82
|
it 'kills all threads' do
|
80
83
|
subject
|
81
|
-
before_thread_count = Thread.list.size
|
82
84
|
100.times { subject.async{ sleep(1) } }
|
83
85
|
sleep(0.1)
|
84
|
-
|
86
|
+
subject.busy_size.should eq(subject.pool_size)
|
85
87
|
subject.kill!
|
86
88
|
sleep(0.1)
|
87
|
-
|
89
|
+
subject.busy_size.should eq(0)
|
88
90
|
end
|
89
91
|
end
|
90
92
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lifeguard
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-09-
|
13
|
+
date: 2016-09-20 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: better_receive
|
@@ -164,7 +164,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
164
164
|
version: '0'
|
165
165
|
segments:
|
166
166
|
- 0
|
167
|
-
hash:
|
167
|
+
hash: 3990094158605576821
|
168
168
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
169
169
|
none: false
|
170
170
|
requirements:
|
@@ -173,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
173
173
|
version: '0'
|
174
174
|
segments:
|
175
175
|
- 0
|
176
|
-
hash:
|
176
|
+
hash: 3990094158605576821
|
177
177
|
requirements: []
|
178
178
|
rubyforge_project:
|
179
179
|
rubygems_version: 1.8.24
|