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.
@@ -2,7 +2,8 @@ language: ruby
2
2
  before_install:
3
3
  - gem install bundler
4
4
  rvm:
5
- - 1.9
6
5
  - 2.0
7
6
  - 2.1
8
- - jruby
7
+ - 2.3
8
+ - jruby-9.1.2.0
9
+ - jruby-9.1.5.0
@@ -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
- new_thread = ::Thread.new(block, args) do |callable, call_args|
20
- ::Thread.current[:__start_time_in_seconds__] = Time.now.to_i
21
- ::Thread.current.abort_on_exception = false
22
-
23
- callable.call(*call_args)
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
@@ -20,7 +20,6 @@ module Lifeguard
20
20
  def run!
21
21
  loop do
22
22
  sleep(@reaping_interval)
23
- @threadpool.prune_busy_threads if @threadpool
24
23
  @threadpool.timeout! if @threadpool
25
24
  end
26
25
  rescue
@@ -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
- prune_busy_threads_without_mutex
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 << ::Thread.new(block, args, self) do |callable, call_args, parent|
72
- begin
73
- ::Thread.current[:__start_time_in_seconds__] = Time.now.to_i
74
- ::Thread.current.abort_on_exception = false
75
- callable.call(*call_args) # should we check the args? pass args?
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 prune_busy_threads
88
- @mutex.synchronize do
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
- prune_busy_threads_without_mutex
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
 
@@ -1,3 +1,3 @@
1
1
  module Lifeguard
2
- VERSION = "0.2.1"
2
+ VERSION = "0.3.0"
3
3
  end
@@ -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(10)
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
- Thread.list.size.should > before_thread_count
86
+ subject.busy_size.should eq(subject.pool_size)
85
87
  subject.kill!
86
88
  sleep(0.1)
87
- Thread.list.size.should eq(before_thread_count)
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.2.1
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-08 00:00:00.000000000 Z
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: -402206971017755019
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: -402206971017755019
176
+ hash: 3990094158605576821
177
177
  requirements: []
178
178
  rubyforge_project:
179
179
  rubygems_version: 1.8.24