parallel 1.21.0 → 1.22.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4dd167566b23262ceacbd640fda95c5e8d0d8149cc430f51ada53765a927cb18
4
- data.tar.gz: 6a21c00b1109d5c665a471aec4a7af7d213ded2fc9123132b6576ee65ceb1758
3
+ metadata.gz: 1b517593727e82ec4dd9a897612cfca6ed731f788b84bceee4166a455bbc339d
4
+ data.tar.gz: a47a4fbac65ebe5ecad57c3d2c78df64f261e3770637cacbb2063b91369538bf
5
5
  SHA512:
6
- metadata.gz: 1f8a810c3b7fa77e8dd2b2539238b856b9b4ea40b5df49cf2cc4af2afbd2a73d9b6f34baab614c41e7b3b8bfe1917413bfbd014f647c5b4b96e7243d5433523d
7
- data.tar.gz: 0bef1c7dc19b4738e228985512ee6cce1915f67ee29161b743821f69366d561ed8c3c5cbd4d9e6829342108fe9f10329563770d1978a660a04c58c0d9e2c8461
6
+ metadata.gz: a4e9dbbbf9c0cbff88e12750fd521ee3f65bd1c0de2ab5a18e1a9b7e96c413cd12cce0de985aef9bd4ca0eb8c5e438cf83ac59c88a74e67e38ef73cc7ac8fac9
7
+ data.tar.gz: 37ddce10ac73b9d722452693914bb889f2d638cbe52fe36ffe37673d6bba9d01601656568408eac29155619df8208892c51861e9033888e549bcaa467ce1f912
@@ -19,7 +19,7 @@ module Parallel
19
19
  when /linux/
20
20
  cores = {} # unique physical ID / core ID combinations
21
21
  phy = 0
22
- IO.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
22
+ File.read("/proc/cpuinfo").scan(/^physical id.*|^core id.*/) do |ln|
23
23
  if ln.start_with?("physical")
24
24
  phy = ln[/\d+/]
25
25
  elsif ln.start_with?("core")
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Parallel
3
- VERSION = Version = '1.21.0' # rubocop:disable Naming/ConstantName
3
+ VERSION = Version = '1.22.0' # rubocop:disable Naming/ConstantName
4
4
  end
data/lib/parallel.rb CHANGED
@@ -264,6 +264,9 @@ module Parallel
264
264
  elsif options[:in_threads]
265
265
  method = :in_threads
266
266
  size = options[method]
267
+ elsif options[:in_ractors]
268
+ method = :in_ractors
269
+ size = options[method]
267
270
  else
268
271
  method = :in_processes
269
272
  if Process.respond_to?(:fork)
@@ -285,6 +288,8 @@ module Parallel
285
288
  work_direct(job_factory, options, &block)
286
289
  elsif method == :in_threads
287
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)
288
293
  else
289
294
  work_in_processes(job_factory, options.merge(count: size), &block)
290
295
  end
@@ -382,6 +387,72 @@ module Parallel
382
387
  exception || results
383
388
  end
384
389
 
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]`"
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
+
385
456
  def work_in_processes(job_factory, options, &blk)
386
457
  workers = create_workers(job_factory, options, &blk)
387
458
  results = []
@@ -426,6 +497,7 @@ module Parallel
426
497
  end
427
498
  end
428
499
  end
500
+
429
501
  exception || results
430
502
  end
431
503
 
@@ -521,12 +593,20 @@ module Parallel
521
593
  end
522
594
 
523
595
  def with_instrumentation(item, index, options)
524
- on_start = options[:start]
525
- on_finish = options[:finish]
526
- options[:mutex].synchronize { on_start.call(item, index) } if on_start
596
+ instrument_start(item, index, options)
527
597
  result = yield
528
- options[:mutex].synchronize { on_finish.call(item, index, result) } if on_finish
598
+ instrument_finish(item, index, result, options)
529
599
  result unless options[:preserve_results] == false
530
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
531
611
  end
532
612
  end
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallel
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.21.0
4
+ version: 1.22.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Michael Grosser
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-09-13 00:00:00.000000000 Z
11
+ date: 2022-03-21 00:00:00.000000000 Z
12
12
  dependencies: []
13
- description:
13
+ description:
14
14
  email: michael@grosser.it
15
15
  executables: []
16
16
  extensions: []
@@ -25,10 +25,10 @@ licenses:
25
25
  - MIT
26
26
  metadata:
27
27
  bug_tracker_uri: https://github.com/grosser/parallel/issues
28
- documentation_uri: https://github.com/grosser/parallel/blob/v1.21.0/Readme.md
29
- source_code_uri: https://github.com/grosser/parallel/tree/v1.21.0
28
+ documentation_uri: https://github.com/grosser/parallel/blob/v1.22.0/Readme.md
29
+ source_code_uri: https://github.com/grosser/parallel/tree/v1.22.0
30
30
  wiki_uri: https://github.com/grosser/parallel/wiki
31
- post_install_message:
31
+ post_install_message:
32
32
  rdoc_options: []
33
33
  require_paths:
34
34
  - lib
@@ -43,8 +43,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
43
43
  - !ruby/object:Gem::Version
44
44
  version: '0'
45
45
  requirements: []
46
- rubygems_version: 3.2.16
47
- signing_key:
46
+ rubygems_version: 3.3.3
47
+ signing_key:
48
48
  specification_version: 4
49
49
  summary: Run any kind of code in parallel processes
50
50
  test_files: []