parallelize 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG.rdoc CHANGED
@@ -1,3 +1,6 @@
1
+ === 0.4.0 / 2012/06/19
2
+ * Added interrupt handling
3
+
1
4
  === 0.3.0 / 2012/06/10
2
5
  * Added `pmap`
3
6
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.4.0
@@ -5,40 +5,62 @@ module Enumerable
5
5
  raise ArgumentError.new("Invalid number of threads") if num_threads < 1
6
6
 
7
7
  threads = []
8
- enum.each_slice((enum.count{true} / num_threads.to_f).ceil) do |slice|
9
- threads <<
10
- case block.arity
11
- when 2
12
- Thread.new(slice, threads.length) { |my_slice, thread_idx|
13
- my_slice.send(method) { |e| yield e, thread_idx }
14
- }
15
- when 1
16
- Thread.new(slice) { |my_slice|
17
- my_slice.send(method) { |e| yield e }
18
- }
19
- when 0, -1
20
- raise ArgumentError.new("Invalid arity: #{block.arity}") if
21
- RUBY_VERSION !~ /^1.8\./ && block.arity == -1
22
- Thread.new(slice) { |my_slice|
23
- my_slice.send(method) { yield }
24
- }
25
- else
26
- raise ArgumentError.new("Invalid arity: #{block.arity}")
8
+
9
+ reap = lambda do |tidx|
10
+ threads[tidx..-1].each do |t|
11
+ t.raise Interrupt if t.alive?
12
+ begin
13
+ t.join
14
+ rescue Exception
15
+ nil
27
16
  end
17
+ end
28
18
  end
29
19
 
30
- exceptions = {}
31
- threads.each_with_index do |thr, idx|
32
- begin
33
- thr.join
34
- rescue Exception => e
35
- if collect_exceptions
36
- exceptions[idx] = e
37
- nil
38
- else
39
- raise e
20
+ begin
21
+ prev_trap = trap('INT') { Thread.current.raise Interrupt }
22
+ enum.each_slice((enum.count{true} / num_threads.to_f).ceil) do |slice|
23
+ threads <<
24
+ case block.arity
25
+ when 2
26
+ Thread.new(slice, threads.length) { |my_slice, thread_idx|
27
+ my_slice.send(method) { |e| yield e, thread_idx }
28
+ }
29
+ when 1
30
+ Thread.new(slice) { |my_slice|
31
+ my_slice.send(method) { |e| yield e }
32
+ }
33
+ when 0, -1
34
+ raise ArgumentError.new("Invalid arity: #{block.arity}") if
35
+ RUBY_VERSION !~ /^1.8\./ && block.arity == -1
36
+ Thread.new(slice) { |my_slice|
37
+ my_slice.send(method) { yield }
38
+ }
39
+ else
40
+ raise ArgumentError.new("Invalid arity: #{block.arity}")
41
+ end
42
+ end
43
+
44
+ exceptions = {}
45
+ threads.each_with_index do |thr, idx|
46
+ begin
47
+ thr.join
48
+ rescue Exception => e
49
+ if collect_exceptions
50
+ exceptions[idx] = e
51
+ nil
52
+ else
53
+ reap.call idx + 1
54
+ raise e
55
+ end
40
56
  end
41
57
  end
58
+ rescue Interrupt
59
+ # Interrupts threads
60
+ reap.call 0
61
+ raise
62
+ ensure
63
+ trap('INT', prev_trap) if prev_trap
42
64
  end
43
65
 
44
66
  unless exceptions.empty?
@@ -137,4 +137,54 @@ class TestParallelize < Test::Unit::TestCase
137
137
  (0..100).pmap(thr) { |e, tidx| "#{e} by #{tidx}" }
138
138
  )
139
139
  end
140
+
141
+ def test_reap
142
+ ic = 0
143
+ t = Thread.new {
144
+ begin
145
+ parallelize(2) do |idx|
146
+ begin
147
+ raise Exception.new if idx == 0
148
+ loop {}
149
+ rescue Interrupt
150
+ puts "Interrupted (#{idx}-#{ic})"
151
+ ic += 1
152
+ end
153
+ end
154
+ rescue Interrupt
155
+ puts "Interrupted (parallelize-#{ic})"
156
+ ic += 1
157
+ rescue Exception
158
+ puts "Exception thrown from a child"
159
+ raise
160
+ end
161
+ }
162
+
163
+ assert_raise(Exception) { t.join }
164
+ assert_equal 1, ic
165
+ end
166
+
167
+ def test_interrupt
168
+ ic = 0
169
+ t = Thread.new {
170
+ begin
171
+ parallelize(2) do |idx|
172
+ begin
173
+ loop {}
174
+ rescue Interrupt
175
+ puts "Interrupted (#{idx}-#{ic})"
176
+ ic += 1
177
+ end
178
+ end
179
+ rescue Interrupt
180
+ puts "Interrupted (parallelize-#{ic})"
181
+ ic += 1
182
+ end
183
+ }
184
+
185
+ sleep 2
186
+ t.raise Interrupt
187
+ t.join
188
+ assert_equal 3, ic
189
+ end
140
190
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallelize
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.4.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-06-10 00:00:00.000000000 Z
12
+ date: 2012-06-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: yard
@@ -81,7 +81,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
81
81
  version: '0'
82
82
  segments:
83
83
  - 0
84
- hash: 4037532998974082938
84
+ hash: -3400073306691178831
85
85
  required_rubygems_version: !ruby/object:Gem::Requirement
86
86
  none: false
87
87
  requirements: