parallel 1.12.1 → 1.22.1
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 +5 -5
- data/lib/parallel/processor_count.rb +28 -77
- data/lib/parallel/version.rb +2 -1
- data/lib/parallel.rb +186 -74
- metadata +9 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 7efbfe49c3df93ae88464b4bd4ce85d1aaccc9c173e1a81e7cf9100fe182982c
|
4
|
+
data.tar.gz: 7e82ff83bd44c96da760d83ab665baed41bc62d53f010987951c805cf41723e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a81cae96dd4dcfa1d287ce3e5893c830de3cb8e305236db4170db81f94de021f187da0d21462b7df5e99310002c14984fbb00aef818936c13d0ae834c1c1b2e7
|
7
|
+
data.tar.gz: 79c099a5f1f8bdad3d9f187829213d242087779605f14fb421f0172c1de1a8f853b4f13045935410a989d845d08e736e9552c8e3b9a6c3763d2dfdd27ede7daf
|
@@ -1,90 +1,41 @@
|
|
1
|
-
|
2
|
-
require 'etc'
|
3
|
-
end
|
4
|
-
|
1
|
+
# frozen_string_literal: true
|
5
2
|
module Parallel
|
3
|
+
# TODO: inline this method into parallel.rb and kill physical_processor_count in next major release
|
6
4
|
module ProcessorCount
|
7
|
-
# Number of processors seen by the OS
|
8
|
-
#
|
9
|
-
# * AIX: /usr/sbin/pmcycles (AIX 5+), /usr/sbin/lsdev
|
10
|
-
# * BSD: /sbin/sysctl
|
11
|
-
# * Cygwin: /proc/cpuinfo
|
12
|
-
# * Darwin: /usr/bin/hwprefs, /usr/sbin/sysctl
|
13
|
-
# * HP-UX: /usr/sbin/ioscan
|
14
|
-
# * IRIX: /usr/sbin/sysconf
|
15
|
-
# * Linux: /proc/cpuinfo
|
16
|
-
# * Minix 3+: /proc/cpuinfo
|
17
|
-
# * Solaris: /usr/sbin/psrinfo
|
18
|
-
# * Tru64 UNIX: /usr/sbin/psrinfo
|
19
|
-
# * UnixWare: /usr/sbin/psrinfo
|
20
|
-
#
|
5
|
+
# Number of processors seen by the OS, used for process scheduling
|
21
6
|
def processor_count
|
22
|
-
|
23
|
-
|
24
|
-
Etc.nprocessors
|
25
|
-
else
|
26
|
-
os_name = RbConfig::CONFIG["target_os"]
|
27
|
-
if os_name =~ /mingw|mswin/
|
28
|
-
require 'win32ole'
|
29
|
-
result = WIN32OLE.connect("winmgmts://").ExecQuery(
|
30
|
-
"select NumberOfLogicalProcessors from Win32_Processor")
|
31
|
-
result.to_enum.collect(&:NumberOfLogicalProcessors).reduce(:+)
|
32
|
-
elsif File.readable?("/proc/cpuinfo")
|
33
|
-
IO.read("/proc/cpuinfo").scan(/^processor/).size
|
34
|
-
elsif File.executable?("/usr/bin/hwprefs")
|
35
|
-
IO.popen("/usr/bin/hwprefs thread_count").read.to_i
|
36
|
-
elsif File.executable?("/usr/sbin/psrinfo")
|
37
|
-
IO.popen("/usr/sbin/psrinfo").read.scan(/^.*on-*line/).size
|
38
|
-
elsif File.executable?("/usr/sbin/ioscan")
|
39
|
-
IO.popen("/usr/sbin/ioscan -kC processor") do |out|
|
40
|
-
out.read.scan(/^.*processor/).size
|
41
|
-
end
|
42
|
-
elsif File.executable?("/usr/sbin/pmcycles")
|
43
|
-
IO.popen("/usr/sbin/pmcycles -m").read.count("\n")
|
44
|
-
elsif File.executable?("/usr/sbin/lsdev")
|
45
|
-
IO.popen("/usr/sbin/lsdev -Cc processor -S 1").read.count("\n")
|
46
|
-
elsif File.executable?("/usr/sbin/sysconf") and os_name =~ /irix/i
|
47
|
-
IO.popen("/usr/sbin/sysconf NPROC_ONLN").read.to_i
|
48
|
-
elsif File.executable?("/usr/sbin/sysctl")
|
49
|
-
IO.popen("/usr/sbin/sysctl -n hw.ncpu").read.to_i
|
50
|
-
elsif File.executable?("/sbin/sysctl")
|
51
|
-
IO.popen("/sbin/sysctl -n hw.ncpu").read.to_i
|
52
|
-
else
|
53
|
-
$stderr.puts "Unknown platform: " + RbConfig::CONFIG["target_os"]
|
54
|
-
$stderr.puts "Assuming 1 processor."
|
55
|
-
1
|
56
|
-
end
|
57
|
-
end
|
58
|
-
end
|
7
|
+
require 'etc'
|
8
|
+
@processor_count ||= Integer(ENV['PARALLEL_PROCESSOR_COUNT'] || Etc.nprocessors)
|
59
9
|
end
|
60
10
|
|
61
11
|
# Number of physical processor cores on the current system.
|
62
|
-
#
|
63
12
|
def physical_processor_count
|
64
13
|
@physical_processor_count ||= begin
|
65
|
-
ppc =
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
14
|
+
ppc =
|
15
|
+
case RbConfig::CONFIG["target_os"]
|
16
|
+
when /darwin[12]/
|
17
|
+
IO.popen("/usr/sbin/sysctl -n hw.physicalcpu").read.to_i
|
18
|
+
when /linux/
|
19
|
+
cores = {} # unique physical ID / core ID combinations
|
20
|
+
phy = 0
|
21
|
+
File.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
|
22
|
+
if ln.start_with?("physical")
|
23
|
+
phy = ln[/\d+/]
|
24
|
+
elsif ln.start_with?("core")
|
25
|
+
cid = "#{phy}:#{ln[/\d+/]}"
|
26
|
+
cores[cid] = true unless cores[cid]
|
27
|
+
end
|
77
28
|
end
|
29
|
+
cores.count
|
30
|
+
when /mswin|mingw/
|
31
|
+
require 'win32ole'
|
32
|
+
result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
|
33
|
+
"select NumberOfCores from Win32_Processor"
|
34
|
+
)
|
35
|
+
result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
|
36
|
+
else
|
37
|
+
processor_count
|
78
38
|
end
|
79
|
-
cores.count
|
80
|
-
when /mswin|mingw/
|
81
|
-
require 'win32ole'
|
82
|
-
result_set = WIN32OLE.connect("winmgmts://").ExecQuery(
|
83
|
-
"select NumberOfCores from Win32_Processor")
|
84
|
-
result_set.to_enum.collect(&:NumberOfCores).reduce(:+)
|
85
|
-
else
|
86
|
-
processor_count
|
87
|
-
end
|
88
39
|
# fall back to logical count if physical info is invalid
|
89
40
|
ppc > 0 ? ppc : processor_count
|
90
41
|
end
|
data/lib/parallel/version.rb
CHANGED
data/lib/parallel.rb
CHANGED
@@ -1,31 +1,40 @@
|
|
1
|
+
# frozen_string_literal: true
|
1
2
|
require 'rbconfig'
|
2
3
|
require 'parallel/version'
|
3
4
|
require 'parallel/processor_count'
|
4
5
|
|
5
6
|
module Parallel
|
6
|
-
extend
|
7
|
+
extend ProcessorCount
|
8
|
+
|
9
|
+
Stop = Object.new.freeze
|
7
10
|
|
8
11
|
class DeadWorker < StandardError
|
9
12
|
end
|
10
13
|
|
11
14
|
class Break < StandardError
|
15
|
+
attr_reader :value
|
16
|
+
|
17
|
+
def initialize(value = nil)
|
18
|
+
super()
|
19
|
+
@value = value
|
20
|
+
end
|
12
21
|
end
|
13
22
|
|
14
|
-
class Kill <
|
23
|
+
class Kill < Break
|
15
24
|
end
|
16
25
|
|
17
26
|
class UndumpableException < StandardError
|
18
27
|
attr_reader :backtrace
|
28
|
+
|
19
29
|
def initialize(original)
|
20
30
|
super "#{original.class}: #{original.message}"
|
21
31
|
@backtrace = original.backtrace
|
22
32
|
end
|
23
33
|
end
|
24
34
|
|
25
|
-
Stop = Object.new
|
26
|
-
|
27
35
|
class ExceptionWrapper
|
28
36
|
attr_reader :exception
|
37
|
+
|
29
38
|
def initialize(exception)
|
30
39
|
# Remove the bindings stack added by the better_errors gem,
|
31
40
|
# because it cannot be marshalled
|
@@ -36,7 +45,7 @@ module Parallel
|
|
36
45
|
@exception =
|
37
46
|
begin
|
38
47
|
Marshal.dump(exception) && exception
|
39
|
-
rescue
|
48
|
+
rescue StandardError
|
40
49
|
UndumpableException.new(exception)
|
41
50
|
end
|
42
51
|
end
|
@@ -45,8 +54,11 @@ module Parallel
|
|
45
54
|
class Worker
|
46
55
|
attr_reader :pid, :read, :write
|
47
56
|
attr_accessor :thread
|
57
|
+
|
48
58
|
def initialize(read, write, pid)
|
49
|
-
@read
|
59
|
+
@read = read
|
60
|
+
@write = write
|
61
|
+
@pid = pid
|
50
62
|
end
|
51
63
|
|
52
64
|
def stop
|
@@ -73,7 +85,7 @@ module Parallel
|
|
73
85
|
rescue EOFError
|
74
86
|
raise DeadWorker
|
75
87
|
end
|
76
|
-
raise result.exception if ExceptionWrapper
|
88
|
+
raise result.exception if result.is_a?(ExceptionWrapper)
|
77
89
|
result
|
78
90
|
end
|
79
91
|
|
@@ -102,7 +114,7 @@ module Parallel
|
|
102
114
|
item, index = @mutex.synchronize do
|
103
115
|
return if @stopped
|
104
116
|
item = @lambda.call
|
105
|
-
@stopped = (item ==
|
117
|
+
@stopped = (item == Stop)
|
106
118
|
return if @stopped
|
107
119
|
[item, @index += 1]
|
108
120
|
end
|
@@ -140,7 +152,7 @@ module Parallel
|
|
140
152
|
end
|
141
153
|
|
142
154
|
def queue_wrapper(array)
|
143
|
-
array.respond_to?(:num_waiting) && array.respond_to?(:pop) &&
|
155
|
+
array.respond_to?(:num_waiting) && array.respond_to?(:pop) && -> { array.pop(false) }
|
144
156
|
end
|
145
157
|
end
|
146
158
|
|
@@ -156,7 +168,7 @@ module Parallel
|
|
156
168
|
|
157
169
|
if @to_be_killed.empty?
|
158
170
|
old_interrupt = trap_interrupt(signal) do
|
159
|
-
|
171
|
+
warn 'Parallel execution interrupted, exiting ...'
|
160
172
|
@to_be_killed.flatten.each { |pid| kill(pid) }
|
161
173
|
end
|
162
174
|
end
|
@@ -200,46 +212,61 @@ module Parallel
|
|
200
212
|
end
|
201
213
|
|
202
214
|
class << self
|
203
|
-
def in_threads(options={:
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
215
|
+
def in_threads(options = { count: 2 })
|
216
|
+
threads = []
|
217
|
+
count, = extract_count_from_options(options)
|
218
|
+
|
219
|
+
Thread.handle_interrupt(Exception => :never) do
|
220
|
+
Thread.handle_interrupt(Exception => :immediate) do
|
221
|
+
count.times do |i|
|
222
|
+
threads << Thread.new { yield(i) }
|
223
|
+
end
|
224
|
+
threads.map(&:value)
|
225
|
+
end
|
226
|
+
ensure
|
227
|
+
threads.each(&:kill)
|
228
|
+
end
|
208
229
|
end
|
209
230
|
|
210
231
|
def in_processes(options = {}, &block)
|
211
232
|
count, options = extract_count_from_options(options)
|
212
233
|
count ||= processor_count
|
213
|
-
map(0...count, options.merge(:
|
234
|
+
map(0...count, options.merge(in_processes: count), &block)
|
214
235
|
end
|
215
236
|
|
216
|
-
def each(array, options={}, &block)
|
217
|
-
map(array, options.merge(:
|
237
|
+
def each(array, options = {}, &block)
|
238
|
+
map(array, options.merge(preserve_results: false), &block)
|
218
239
|
end
|
219
240
|
|
220
241
|
def any?(*args, &block)
|
221
242
|
raise "You must provide a block when calling #any?" if block.nil?
|
222
|
-
!each(*args) { |*a| raise
|
243
|
+
!each(*args) { |*a| raise Kill if block.call(*a) }
|
223
244
|
end
|
224
245
|
|
225
246
|
def all?(*args, &block)
|
226
247
|
raise "You must provide a block when calling #all?" if block.nil?
|
227
|
-
!!each(*args) { |*a| raise
|
248
|
+
!!each(*args) { |*a| raise Kill unless block.call(*a) }
|
228
249
|
end
|
229
250
|
|
230
|
-
def each_with_index(array, options={}, &block)
|
231
|
-
each(array, options.merge(:
|
251
|
+
def each_with_index(array, options = {}, &block)
|
252
|
+
each(array, options.merge(with_index: true), &block)
|
232
253
|
end
|
233
254
|
|
234
255
|
def map(source, options = {}, &block)
|
256
|
+
options = options.dup
|
235
257
|
options[:mutex] = Mutex.new
|
236
258
|
|
237
|
-
if
|
259
|
+
if options[:in_processes] && options[:in_threads]
|
260
|
+
raise ArgumentError, "Please specify only one of `in_processes` or `in_threads`."
|
261
|
+
elsif RUBY_PLATFORM =~ (/java/) && !(options[:in_processes])
|
238
262
|
method = :in_threads
|
239
263
|
size = options[method] || processor_count
|
240
264
|
elsif options[:in_threads]
|
241
265
|
method = :in_threads
|
242
266
|
size = options[method]
|
267
|
+
elsif options[:in_ractors]
|
268
|
+
method = :in_ractors
|
269
|
+
size = options[method]
|
243
270
|
else
|
244
271
|
method = :in_processes
|
245
272
|
if Process.respond_to?(:fork)
|
@@ -256,26 +283,35 @@ module Parallel
|
|
256
283
|
options[:return_results] = (options[:preserve_results] != false || !!options[:finish])
|
257
284
|
add_progress_bar!(job_factory, options)
|
258
285
|
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
286
|
+
result =
|
287
|
+
if size == 0
|
288
|
+
work_direct(job_factory, options, &block)
|
289
|
+
elsif method == :in_threads
|
290
|
+
work_in_threads(job_factory, options.merge(count: size), &block)
|
291
|
+
elsif method == :in_ractors
|
292
|
+
work_in_ractors(job_factory, options.merge(count: size), &block)
|
293
|
+
else
|
294
|
+
work_in_processes(job_factory, options.merge(count: size), &block)
|
295
|
+
end
|
296
|
+
|
297
|
+
return result.value if result.is_a?(Break)
|
298
|
+
raise result if result.is_a?(Exception)
|
299
|
+
options[:return_results] ? result : source
|
300
|
+
end
|
301
|
+
|
302
|
+
def map_with_index(array, options = {}, &block)
|
303
|
+
map(array, options.merge(with_index: true), &block)
|
269
304
|
end
|
270
305
|
|
271
|
-
def
|
272
|
-
map(
|
306
|
+
def flat_map(*args, &block)
|
307
|
+
map(*args, &block).flatten(1)
|
273
308
|
end
|
274
309
|
|
275
310
|
def worker_number
|
276
311
|
Thread.current[:parallel_worker_number]
|
277
312
|
end
|
278
313
|
|
314
|
+
# TODO: this does not work when doing threads in forks, so should remove and yield the number instead if needed
|
279
315
|
def worker_number=(worker_num)
|
280
316
|
Thread.current[:parallel_worker_number] = worker_num
|
281
317
|
end
|
@@ -318,10 +354,10 @@ module Parallel
|
|
318
354
|
call_with_index(item, index, options, &block)
|
319
355
|
end
|
320
356
|
end
|
321
|
-
rescue
|
357
|
+
rescue StandardError
|
322
358
|
exception = $!
|
323
359
|
end
|
324
|
-
|
360
|
+
exception || results
|
325
361
|
ensure
|
326
362
|
self.worker_number = nil
|
327
363
|
end
|
@@ -342,21 +378,83 @@ module Parallel
|
|
342
378
|
call_with_index(item, index, options, &block)
|
343
379
|
end
|
344
380
|
results_mutex.synchronize { results[index] = result }
|
345
|
-
rescue
|
381
|
+
rescue StandardError
|
346
382
|
exception = $!
|
347
383
|
end
|
348
384
|
end
|
349
385
|
end
|
350
386
|
|
351
|
-
|
387
|
+
exception || results
|
352
388
|
end
|
353
389
|
|
354
|
-
def
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
390
|
+
def work_in_ractors(job_factory, options)
|
391
|
+
exception = nil
|
392
|
+
results = []
|
393
|
+
results_mutex = Mutex.new # arrays are not thread-safe on jRuby
|
394
|
+
|
395
|
+
callback = options[:ractor]
|
396
|
+
if block_given? || !callback
|
397
|
+
raise ArgumentError, "pass the code you want to execute as `ractor: [ClassName, :method_name]`"
|
359
398
|
end
|
399
|
+
|
400
|
+
# build
|
401
|
+
ractors = Array.new(options.fetch(:count)) do
|
402
|
+
Ractor.new do
|
403
|
+
loop do
|
404
|
+
got = receive
|
405
|
+
(klass, method_name), item, index = got
|
406
|
+
break if index == :break
|
407
|
+
begin
|
408
|
+
Ractor.yield [nil, klass.send(method_name, item), item, index]
|
409
|
+
rescue StandardError => e
|
410
|
+
Ractor.yield [e, nil, item, index]
|
411
|
+
end
|
412
|
+
end
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
# start
|
417
|
+
ractors.dup.each do |ractor|
|
418
|
+
if set = job_factory.next
|
419
|
+
item, index = set
|
420
|
+
instrument_start item, index, options
|
421
|
+
ractor.send [callback, item, index]
|
422
|
+
else
|
423
|
+
ractor.send([[nil, nil], nil, :break]) # stop the ractor
|
424
|
+
ractors.delete ractor
|
425
|
+
end
|
426
|
+
end
|
427
|
+
|
428
|
+
# replace with new items
|
429
|
+
while set = job_factory.next
|
430
|
+
item_next, index_next = set
|
431
|
+
done, (exception, result, item, index) = Ractor.select(*ractors)
|
432
|
+
if exception
|
433
|
+
ractors.delete done
|
434
|
+
break
|
435
|
+
end
|
436
|
+
instrument_finish item, index, result, options
|
437
|
+
results_mutex.synchronize { results[index] = (options[:preserve_results] == false ? nil : result) }
|
438
|
+
|
439
|
+
instrument_start item_next, index_next, options
|
440
|
+
done.send([callback, item_next, index_next])
|
441
|
+
end
|
442
|
+
|
443
|
+
# finish
|
444
|
+
ractors.each do |ractor|
|
445
|
+
(new_exception, result, item, index) = ractor.take
|
446
|
+
exception ||= new_exception
|
447
|
+
next if new_exception
|
448
|
+
instrument_finish item, index, result, options
|
449
|
+
results_mutex.synchronize { results[index] = (options[:preserve_results] == false ? nil : result) }
|
450
|
+
ractor.send([[nil, nil], nil, :break]) # stop the ractor
|
451
|
+
end
|
452
|
+
|
453
|
+
exception || results
|
454
|
+
end
|
455
|
+
|
456
|
+
def work_in_processes(job_factory, options, &blk)
|
457
|
+
workers = create_workers(job_factory, options, &blk)
|
360
458
|
results = []
|
361
459
|
results_mutex = Mutex.new # arrays are not thread-safe
|
362
460
|
exception = nil
|
@@ -364,6 +462,8 @@ module Parallel
|
|
364
462
|
UserInterruptHandler.kill_on_ctrl_c(workers.map(&:pid), options) do
|
365
463
|
in_threads(options) do |i|
|
366
464
|
worker = workers[i]
|
465
|
+
worker.thread = Thread.current
|
466
|
+
worked = false
|
367
467
|
|
368
468
|
begin
|
369
469
|
loop do
|
@@ -372,44 +472,44 @@ module Parallel
|
|
372
472
|
break unless index
|
373
473
|
|
374
474
|
if options[:isolation]
|
375
|
-
worker = replace_worker(job_factory, workers, i, options, blk)
|
475
|
+
worker = replace_worker(job_factory, workers, i, options, blk) if worked
|
476
|
+
worked = true
|
477
|
+
worker.thread = Thread.current
|
376
478
|
end
|
377
479
|
|
378
|
-
worker.thread = Thread.current
|
379
|
-
|
380
480
|
begin
|
381
481
|
result = with_instrumentation item, index, options do
|
382
482
|
worker.work(job_factory.pack(item, index))
|
383
483
|
end
|
384
484
|
results_mutex.synchronize { results[index] = result } # arrays are not threads safe on jRuby
|
385
|
-
rescue
|
386
|
-
exception =
|
387
|
-
if
|
485
|
+
rescue StandardError => e
|
486
|
+
exception = e
|
487
|
+
if exception.is_a?(Kill)
|
388
488
|
(workers - [worker]).each do |w|
|
389
|
-
w.thread
|
489
|
+
w.thread&.kill
|
390
490
|
UserInterruptHandler.kill(w.pid)
|
391
491
|
end
|
392
492
|
end
|
393
493
|
end
|
394
494
|
end
|
395
495
|
ensure
|
396
|
-
worker.stop
|
496
|
+
worker.stop
|
397
497
|
end
|
398
498
|
end
|
399
499
|
end
|
400
500
|
|
401
|
-
|
501
|
+
exception || results
|
402
502
|
end
|
403
503
|
|
404
|
-
def replace_worker(job_factory, workers,
|
504
|
+
def replace_worker(job_factory, workers, index, options, blk)
|
405
505
|
options[:mutex].synchronize do
|
406
506
|
# old worker is no longer used ... stop it
|
407
|
-
worker = workers[
|
408
|
-
worker.stop
|
507
|
+
worker = workers[index]
|
508
|
+
worker.stop
|
409
509
|
|
410
510
|
# create a new replacement worker
|
411
511
|
running = workers - [worker]
|
412
|
-
workers[
|
512
|
+
workers[index] = worker(job_factory, options.merge(started_workers: running, worker_number: index), &blk)
|
413
513
|
end
|
414
514
|
end
|
415
515
|
|
@@ -451,21 +551,25 @@ module Parallel
|
|
451
551
|
until read.eof?
|
452
552
|
data = Marshal.load(read)
|
453
553
|
item, index = job_factory.unpack(data)
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
554
|
+
|
555
|
+
result =
|
556
|
+
begin
|
557
|
+
call_with_index(item, index, options, &block)
|
558
|
+
# https://github.com/rspec/rspec-support/blob/673133cdd13b17077b3d88ece8d7380821f8d7dc/lib/rspec/support.rb#L132-L140
|
559
|
+
rescue NoMemoryError, SignalException, Interrupt, SystemExit # rubocop:disable Lint/ShadowedException
|
560
|
+
raise $!
|
561
|
+
rescue Exception # # rubocop:disable Lint/RescueException
|
562
|
+
ExceptionWrapper.new($!)
|
563
|
+
end
|
564
|
+
|
565
|
+
begin
|
566
|
+
Marshal.dump(result, write)
|
567
|
+
rescue Errno::EPIPE
|
568
|
+
return # parent thread already dead
|
458
569
|
end
|
459
|
-
Marshal.dump(result, write)
|
460
570
|
end
|
461
571
|
end
|
462
572
|
|
463
|
-
def handle_exception(exception, results)
|
464
|
-
return nil if [Parallel::Break, Parallel::Kill].include? exception.class
|
465
|
-
raise exception if exception
|
466
|
-
results
|
467
|
-
end
|
468
|
-
|
469
573
|
# options is either a Integer or a Hash with :count
|
470
574
|
def extract_count_from_options(options)
|
471
575
|
if options.is_a?(Hash)
|
@@ -480,21 +584,29 @@ module Parallel
|
|
480
584
|
def call_with_index(item, index, options, &block)
|
481
585
|
args = [item]
|
482
586
|
args << index if options[:with_index]
|
587
|
+
results = block.call(*args)
|
483
588
|
if options[:return_results]
|
484
|
-
|
589
|
+
results
|
485
590
|
else
|
486
|
-
block.call(*args)
|
487
591
|
nil # avoid GC overhead of passing large results around
|
488
592
|
end
|
489
593
|
end
|
490
594
|
|
491
595
|
def with_instrumentation(item, index, options)
|
492
|
-
|
493
|
-
on_finish = options[:finish]
|
494
|
-
options[:mutex].synchronize { on_start.call(item, index) } if on_start
|
596
|
+
instrument_start(item, index, options)
|
495
597
|
result = yield
|
496
|
-
|
598
|
+
instrument_finish(item, index, result, options)
|
497
599
|
result unless options[:preserve_results] == false
|
498
600
|
end
|
601
|
+
|
602
|
+
def instrument_finish(item, index, result, options)
|
603
|
+
return unless on_finish = options[:finish]
|
604
|
+
options[:mutex].synchronize { on_finish.call(item, index, result) }
|
605
|
+
end
|
606
|
+
|
607
|
+
def instrument_start(item, index, options)
|
608
|
+
return unless on_start = options[:start]
|
609
|
+
options[:mutex].synchronize { on_start.call(item, index) }
|
610
|
+
end
|
499
611
|
end
|
500
612
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: parallel
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.22.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Grosser
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-03-25 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description:
|
14
14
|
email: michael@grosser.it
|
@@ -23,7 +23,11 @@ files:
|
|
23
23
|
homepage: https://github.com/grosser/parallel
|
24
24
|
licenses:
|
25
25
|
- MIT
|
26
|
-
metadata:
|
26
|
+
metadata:
|
27
|
+
bug_tracker_uri: https://github.com/grosser/parallel/issues
|
28
|
+
documentation_uri: https://github.com/grosser/parallel/blob/v1.22.1/Readme.md
|
29
|
+
source_code_uri: https://github.com/grosser/parallel/tree/v1.22.1
|
30
|
+
wiki_uri: https://github.com/grosser/parallel/wiki
|
27
31
|
post_install_message:
|
28
32
|
rdoc_options: []
|
29
33
|
require_paths:
|
@@ -32,15 +36,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
32
36
|
requirements:
|
33
37
|
- - ">="
|
34
38
|
- !ruby/object:Gem::Version
|
35
|
-
version:
|
39
|
+
version: '2.5'
|
36
40
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
37
41
|
requirements:
|
38
42
|
- - ">="
|
39
43
|
- !ruby/object:Gem::Version
|
40
44
|
version: '0'
|
41
45
|
requirements: []
|
42
|
-
|
43
|
-
rubygems_version: 2.5.1
|
46
|
+
rubygems_version: 3.1.6
|
44
47
|
signing_key:
|
45
48
|
specification_version: 4
|
46
49
|
summary: Run any kind of code in parallel processes
|