in_threads 1.5.1 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/check.yml +51 -0
- data/.github/workflows/rubocop.yml +16 -0
- data/.rubocop.yml +20 -9
- data/CHANGELOG.markdown +19 -0
- data/Gemfile +2 -4
- data/LICENSE.txt +1 -1
- data/README.markdown +23 -12
- data/in_threads.gemspec +5 -6
- data/lib/in_threads.rb +46 -19
- data/spec/in_threads_spec.rb +57 -19
- metadata +34 -13
- data/.travis.yml +0 -30
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9ab96a79a5ad21d6198f4c91e689a37343371ca5932a30d695c91f8f8949a9c5
|
4
|
+
data.tar.gz: 91e41ba4f9073cff55f925e40cbc8728893974ec365a440b1f57cafd315ce4be
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0c03797c1506c3bc73b1fd8191ba931f21c63c30e56a897bc309815a461eaa2baa368e7daa88a2023113c954c1016666f0b267cfa11b01455d59b3af4d0999f7
|
7
|
+
data.tar.gz: 274d7a37b752f0f673eb575a348422999b177cdd56e9519f11dbbee0305bd16b17aceccdfd08f1c2ba12b46c8119a309e1a4cc88f8ff3be6078940dc579f96f0
|
@@ -0,0 +1,51 @@
|
|
1
|
+
name: check
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
pull_request:
|
5
|
+
schedule:
|
6
|
+
- cron: 45 4 * * 3
|
7
|
+
jobs:
|
8
|
+
check:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
strategy:
|
11
|
+
matrix:
|
12
|
+
ruby:
|
13
|
+
- '2.0'
|
14
|
+
- '2.1'
|
15
|
+
- '2.2'
|
16
|
+
- '2.3'
|
17
|
+
- '2.4'
|
18
|
+
- '2.5'
|
19
|
+
- '2.6'
|
20
|
+
- '2.7'
|
21
|
+
- '3.0'
|
22
|
+
- '3.1'
|
23
|
+
- jruby-9.1
|
24
|
+
- jruby-9.2
|
25
|
+
- jruby-9.3
|
26
|
+
include:
|
27
|
+
- ruby: ruby-head
|
28
|
+
allow-failure: allow-failure
|
29
|
+
fail-fast: false
|
30
|
+
continue-on-error: ${{ matrix.allow-failure && true || false }}
|
31
|
+
timeout-minutes: 5
|
32
|
+
steps:
|
33
|
+
- uses: actions/checkout@v2
|
34
|
+
- uses: ruby/setup-ruby@v1
|
35
|
+
with:
|
36
|
+
ruby-version: "${{ matrix.ruby }}"
|
37
|
+
bundler-cache: true
|
38
|
+
- run: bundle exec rspec --format documentation
|
39
|
+
legacy:
|
40
|
+
runs-on: ubuntu-latest
|
41
|
+
container: ${{ matrix.container }}
|
42
|
+
strategy:
|
43
|
+
matrix:
|
44
|
+
container:
|
45
|
+
- rspec/ci:1.8.7
|
46
|
+
- rspec/ci:1.9.3
|
47
|
+
fail-fast: false
|
48
|
+
steps:
|
49
|
+
- uses: actions/checkout@v2
|
50
|
+
- run: bundle install
|
51
|
+
- run: bundle exec rspec --format documentation
|
@@ -0,0 +1,16 @@
|
|
1
|
+
name: rubocop
|
2
|
+
on:
|
3
|
+
push:
|
4
|
+
pull_request:
|
5
|
+
schedule:
|
6
|
+
- cron: 45 4 * * 3
|
7
|
+
jobs:
|
8
|
+
rubocop:
|
9
|
+
runs-on: ubuntu-latest
|
10
|
+
steps:
|
11
|
+
- uses: actions/checkout@v2
|
12
|
+
- uses: ruby/setup-ruby@v1
|
13
|
+
with:
|
14
|
+
ruby-version: '3.1'
|
15
|
+
bundler-cache: true
|
16
|
+
- run: bundle exec rubocop
|
data/.rubocop.yml
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
AllCops:
|
2
2
|
Exclude:
|
3
3
|
- '*.gemspec'
|
4
|
+
- 'vendor/bundle/**/*'
|
5
|
+
NewCops: enable
|
4
6
|
|
5
7
|
Layout/AccessModifierIndentation:
|
6
8
|
EnforcedStyle: outdent
|
@@ -14,9 +16,12 @@ Layout/DotPosition:
|
|
14
16
|
Layout/EndAlignment:
|
15
17
|
EnforcedStyleAlignWith: variable
|
16
18
|
|
17
|
-
Layout/
|
19
|
+
Layout/FirstHashElementIndentation:
|
18
20
|
EnforcedStyle: consistent
|
19
21
|
|
22
|
+
Layout/LineLength:
|
23
|
+
Max: 120
|
24
|
+
|
20
25
|
Layout/RescueEnsureAlignment:
|
21
26
|
Enabled: false
|
22
27
|
|
@@ -33,10 +38,10 @@ Lint/AmbiguousBlockAssociation:
|
|
33
38
|
Lint/EnsureReturn:
|
34
39
|
Enabled: false
|
35
40
|
|
36
|
-
Lint/
|
41
|
+
Lint/RedundantRequireStatement:
|
37
42
|
Enabled: false
|
38
43
|
|
39
|
-
Lint/
|
44
|
+
Lint/RescueException:
|
40
45
|
Enabled: false
|
41
46
|
|
42
47
|
Metrics/AbcSize:
|
@@ -52,24 +57,30 @@ Metrics/ClassLength:
|
|
52
57
|
Metrics/CyclomaticComplexity:
|
53
58
|
Max: 10
|
54
59
|
|
55
|
-
Metrics/LineLength:
|
56
|
-
Max: 120
|
57
|
-
|
58
60
|
Metrics/MethodLength:
|
59
61
|
Max: 30
|
60
62
|
|
61
|
-
Performance/RedundantBlockCall:
|
62
|
-
Enabled: false
|
63
|
-
|
64
63
|
Style/DoubleNegation:
|
65
64
|
Enabled: false
|
66
65
|
|
66
|
+
Style/HashEachMethods:
|
67
|
+
Enabled: true
|
68
|
+
|
67
69
|
Style/HashSyntax:
|
68
70
|
EnforcedStyle: hash_rockets
|
69
71
|
|
72
|
+
Style/HashTransformKeys:
|
73
|
+
Enabled: false
|
74
|
+
|
75
|
+
Style/HashTransformValues:
|
76
|
+
Enabled: false
|
77
|
+
|
70
78
|
Style/IfUnlessModifier:
|
71
79
|
Enabled: false
|
72
80
|
|
81
|
+
Style/OptionalBooleanParameter:
|
82
|
+
Enabled: false
|
83
|
+
|
73
84
|
Style/ParallelAssignment:
|
74
85
|
Enabled: false
|
75
86
|
|
data/CHANGELOG.markdown
CHANGED
@@ -2,6 +2,25 @@
|
|
2
2
|
|
3
3
|
## unreleased
|
4
4
|
|
5
|
+
## v1.6.0 (2022-01-18)
|
6
|
+
|
7
|
+
* Fix return for shortcut `enum.in_threads{ break … }` vs `enum.in_threads.each{ break … }` [@toy](https://github.com/toy)
|
8
|
+
* Switch `each_with_object` to run in threads, unlike inject/reduce there is no contradiction, care should be taken if passed object is not thread safe [@toy](https://github.com/toy)
|
9
|
+
* Switch `to_h` (ruby >= 2.6) and `to_set` to run in threads, they accept block to apply before creating Hash and Set respectively [@toy](https://github.com/toy)
|
10
|
+
* Register `compact` added in 3.1 to run without threads (as it doesn't accept block) [@toy](https://github.com/toy)
|
11
|
+
|
12
|
+
## v1.5.4 (2019-12-26)
|
13
|
+
|
14
|
+
* Register `filter_map` to run in threads and `tally` to run without threads (as it doesn't accept block) [@toy](https://github.com/toy)
|
15
|
+
|
16
|
+
## v1.5.3 (2019-07-14)
|
17
|
+
|
18
|
+
* Remove deprecated `rubyforge_project` attribute from gemspec [rubygems/rubygems#2436](https://github.com/rubygems/rubygems/pull/2436) [@toy](https://github.com/toy)
|
19
|
+
|
20
|
+
## v1.5.2 (2019-05-25)
|
21
|
+
|
22
|
+
* Enable frozen string literals [@toy](https://github.com/toy)
|
23
|
+
|
5
24
|
## v1.5.1 (2018-12-30)
|
6
25
|
|
7
26
|
* Register `chain` to run without threads [@toy](https://github.com/toy)
|
data/Gemfile
CHANGED
data/LICENSE.txt
CHANGED
data/README.markdown
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
[![Gem Version](https://img.shields.io/gem/v/in_threads
|
2
|
-
[![Build Status](https://img.shields.io/
|
3
|
-
[![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/in_threads
|
4
|
-
[![Depfu](https://
|
5
|
-
[![Inch CI](https://inch-ci.org/github/toy/in_threads.svg?branch=master
|
1
|
+
[![Gem Version](https://img.shields.io/gem/v/in_threads?logo=rubygems)](https://rubygems.org/gems/in_threads)
|
2
|
+
[![Build Status](https://img.shields.io/github/workflow/status/toy/in_threads/check/master?logo=github)](https://github.com/toy/in_threads/actions/workflows/check.yml)
|
3
|
+
[![Code Climate](https://img.shields.io/codeclimate/maintainability/toy/in_threads?logo=codeclimate)](https://codeclimate.com/github/toy/in_threads)
|
4
|
+
[![Depfu](https://img.shields.io/depfu/toy/in_threads)](https://depfu.com/github/toy/in_threads)
|
5
|
+
[![Inch CI](https://inch-ci.org/github/toy/in_threads.svg?branch=master)](https://inch-ci.org/github/toy/in_threads)
|
6
6
|
|
7
7
|
# in_threads
|
8
8
|
|
@@ -25,13 +25,13 @@ gem 'in_threads'
|
|
25
25
|
...and install it with [Bundler](http://bundler.io).
|
26
26
|
|
27
27
|
```sh
|
28
|
-
|
28
|
+
bundle install
|
29
29
|
```
|
30
30
|
|
31
31
|
Or install globally:
|
32
32
|
|
33
33
|
```sh
|
34
|
-
|
34
|
+
gem install in_threads
|
35
35
|
```
|
36
36
|
|
37
37
|
## Usage
|
@@ -90,9 +90,20 @@ urls.in_threads.all? { |url| HTTP.get(url).status == 200 }
|
|
90
90
|
urls.in_threads.any? { |url| HTTP.get(url).status == 404 }
|
91
91
|
```
|
92
92
|
|
93
|
-
|
94
|
-
|
95
|
-
|
93
|
+
### Compatibility
|
94
|
+
|
95
|
+
All methods of `Enumerable` with a block can be used if block calls are evaluated independently, so following will
|
96
|
+
|
97
|
+
`all?`, `any?`, `collect_concat`, `collect`, `count`, `cycle`, `detect`, `drop_while`, `each_cons`, `each_entry`,
|
98
|
+
`each_slice`, `each_with_index`, `each_with_object`, `each`, `enum_cons`, `enum_slice`, `enum_with_index`,
|
99
|
+
`filter_map`, `filter`, `find_all`, `find_index`, `find`, `flat_map`, `group_by`, `map`, `max_by`, `min_by`,
|
100
|
+
`minmax_by`, `none?`, `one?`, `partition`, `reject`, `reverse_each`, `select`, `sort_by`, `sum`, `take_while`, `to_h`,
|
101
|
+
`to_set`, `uniq`, `zip`.
|
102
|
+
|
103
|
+
Following either don't accept block (like `first`), depend on previous block evaluation (like `inject`) or return an enumerator (like `chunk`), so will simply act as if `in_threads` wasn't used:
|
104
|
+
|
105
|
+
`chain`, `chunk_while`, `chunk`, `compact`, `drop`, `entries`, `first`, `include?`, `inject`, `lazy`, `max`, `member?`,
|
106
|
+
`minmax`, `min`, `reduce`, `slice_after`, `slice_before`, `slice_when`, `sort`, `take`, `tally`, `to_a`.
|
96
107
|
|
97
108
|
### Break and exceptions
|
98
109
|
|
@@ -100,8 +111,8 @@ Exceptions are caught and re-thrown after allowing blocks that are still running
|
|
100
111
|
|
101
112
|
**IMPORTANT**: only the first encountered exception is propagated, so it is recommended to handle exceptions in the block.
|
102
113
|
|
103
|
-
`break` is handled in ruby >= 1.9 and should be handled in jruby [after 9.1.9.0](https://github.com/jruby/jruby/issues/4697). Handling is done in special way: as blocks are run outside of original context, calls to `break` cause `LocalJumpError` which is caught and its result is returned.
|
114
|
+
`break` is handled in ruby >= 1.9 and should be handled in jruby [9.1 after 9.1.9.0](https://github.com/jruby/jruby/issues/4697) and [9.2 and 9.3 after #7009](https://github.com/jruby/jruby/issues/7009). Handling is done in special way: as blocks are run outside of original context, calls to `break` cause `LocalJumpError` which is caught and its result is returned.
|
104
115
|
|
105
116
|
## Copyright
|
106
117
|
|
107
|
-
Copyright (c) 2009-
|
118
|
+
Copyright (c) 2009-2022 Ivan Kuchin. See LICENSE.txt for details.
|
data/in_threads.gemspec
CHANGED
@@ -2,14 +2,12 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'in_threads'
|
5
|
-
s.version = '1.
|
5
|
+
s.version = '1.6.0'
|
6
6
|
s.summary = %q{Run all possible enumerable methods in concurrent/parallel threads}
|
7
|
-
s.homepage = "
|
7
|
+
s.homepage = "https://github.com/toy/#{s.name}"
|
8
8
|
s.authors = ['Ivan Kuchin']
|
9
9
|
s.license = 'MIT'
|
10
10
|
|
11
|
-
s.rubyforge_project = s.name
|
12
|
-
|
13
11
|
s.metadata = {
|
14
12
|
'bug_tracker_uri' => "https://github.com/toy/#{s.name}/issues",
|
15
13
|
'changelog_uri' => "https://github.com/toy/#{s.name}/blob/master/CHANGELOG.markdown",
|
@@ -24,7 +22,8 @@ Gem::Specification.new do |s|
|
|
24
22
|
|
25
23
|
s.add_development_dependency 'rspec', '~> 3.0'
|
26
24
|
s.add_development_dependency 'rspec-retry', '~> 0.3'
|
27
|
-
if RUBY_VERSION >= '2.
|
28
|
-
s.add_development_dependency 'rubocop', '~>
|
25
|
+
if RUBY_VERSION >= '2.5'
|
26
|
+
s.add_development_dependency 'rubocop', '~> 1.22', '!= 1.22.2'
|
27
|
+
s.add_development_dependency 'rubocop-rspec', '~> 2.0'
|
29
28
|
end
|
30
29
|
end
|
data/lib/in_threads.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'thread'
|
2
4
|
require 'delegate'
|
5
|
+
require 'set'
|
3
6
|
|
4
7
|
Enumerable.class_eval do
|
5
8
|
# Run enumerable method blocks in threads
|
@@ -31,17 +34,23 @@ class InThreads < SimpleDelegator
|
|
31
34
|
protected :__getobj__, :__setobj__
|
32
35
|
|
33
36
|
attr_reader :enumerable, :thread_count
|
34
|
-
|
37
|
+
|
38
|
+
def self.new(enumerable, thread_count = 10, &block)
|
39
|
+
if block
|
40
|
+
super.each(&block)
|
41
|
+
else
|
42
|
+
super
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
def initialize(enumerable, thread_count = 10)
|
35
47
|
super(enumerable)
|
48
|
+
|
36
49
|
@enumerable, @thread_count = enumerable, thread_count.to_i
|
37
|
-
unless enumerable.is_a?(Enumerable)
|
38
|
-
fail ArgumentError, '`enumerable` should include Enumerable.'
|
39
|
-
end
|
40
|
-
if thread_count < 2
|
41
|
-
fail ArgumentError, '`thread_count` can\'t be less than 2.'
|
42
|
-
end
|
43
50
|
|
44
|
-
|
51
|
+
fail ArgumentError, '`enumerable` should include Enumerable.' unless enumerable.is_a?(Enumerable)
|
52
|
+
|
53
|
+
fail ArgumentError, '`thread_count` can\'t be less than 2.' if thread_count < 2
|
45
54
|
end
|
46
55
|
|
47
56
|
# Creates new instance using underlying enumerable and new thread_count
|
@@ -66,13 +75,13 @@ class InThreads < SimpleDelegator
|
|
66
75
|
next if ignore_undefined && !enumerable_method?(method)
|
67
76
|
|
68
77
|
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
69
|
-
def #{method}(*args, &block)
|
70
|
-
if block
|
71
|
-
#{runner}(:#{method}, *args, &block)
|
72
|
-
else
|
73
|
-
enumerable.#{method}(*args)
|
74
|
-
end
|
75
|
-
end
|
78
|
+
def #{method}(*args, &block) # def foo_bar(*args, &block)
|
79
|
+
if block # if block
|
80
|
+
#{runner}(:#{method}, *args, &block) # run_in_threads_method(:foo_bar, *args, &block)
|
81
|
+
else # else
|
82
|
+
enumerable.#{method}(*args) # enumerable.foo_bar(*args)
|
83
|
+
end # end
|
84
|
+
end # end
|
76
85
|
RUBY
|
77
86
|
end
|
78
87
|
end
|
@@ -92,6 +101,7 @@ class InThreads < SimpleDelegator
|
|
92
101
|
zip
|
93
102
|
cycle
|
94
103
|
each_entry
|
104
|
+
each_with_object
|
95
105
|
], :ignore_undefined => true
|
96
106
|
use :run_in_threads_use_block_result, :for => %w[
|
97
107
|
all? any? none? one?
|
@@ -99,21 +109,38 @@ class InThreads < SimpleDelegator
|
|
99
109
|
partition find_all select filter reject count
|
100
110
|
collect map group_by max_by min_by minmax_by sort_by sum uniq
|
101
111
|
flat_map collect_concat
|
112
|
+
filter_map
|
113
|
+
to_set
|
102
114
|
], :ignore_undefined => true
|
103
115
|
|
104
|
-
|
116
|
+
DEPENDENT_BLOCK_CALLS = %w[
|
105
117
|
inject reduce
|
106
118
|
max min minmax sort
|
107
|
-
|
119
|
+
].map(&:to_sym)
|
120
|
+
|
121
|
+
ENUMERATOR_RETURNED = %w[
|
122
|
+
chunk chunk_while slice_before slice_after slice_when
|
123
|
+
].map(&:to_sym)
|
124
|
+
|
125
|
+
BLOCKLESS_METHODS = %w[
|
126
|
+
entries to_a
|
108
127
|
drop take
|
109
128
|
first
|
110
129
|
include? member?
|
111
|
-
each_with_object
|
112
|
-
chunk chunk_while slice_before slice_after slice_when
|
113
130
|
lazy
|
114
131
|
chain
|
132
|
+
tally
|
133
|
+
compact
|
115
134
|
].map(&:to_sym)
|
116
135
|
|
136
|
+
if enumerable_method?(:to_h) && [[0, 0]].to_h{ [1, 1] } == {1 => 1}
|
137
|
+
use :run_in_threads_use_block_result, :for => %w[to_h]
|
138
|
+
else
|
139
|
+
BLOCKLESS_METHODS << :to_h
|
140
|
+
end
|
141
|
+
|
142
|
+
INCOMPATIBLE_METHODS = DEPENDENT_BLOCK_CALLS + ENUMERATOR_RETURNED + BLOCKLESS_METHODS
|
143
|
+
|
117
144
|
# Special case method, works by applying `run_in_threads_use_block_result` with
|
118
145
|
# map on enumerable returned by blockless run
|
119
146
|
def grep(*args, &block)
|
data/spec/in_threads_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'rspec'
|
2
4
|
require 'rspec/retry'
|
3
5
|
require 'in_threads'
|
@@ -16,7 +18,12 @@ end
|
|
16
18
|
# not in jruby in mri < 1.9
|
17
19
|
# https://github.com/jruby/jruby/issues/4697
|
18
20
|
SKIP_IF_BREAK_IN_THREAD_IS_IGNORED = begin
|
19
|
-
|
21
|
+
proc do |&block|
|
22
|
+
Thread.new do
|
23
|
+
Thread.current.report_on_exception = false if Thread.current.respond_to?(:report_on_exception=)
|
24
|
+
block.call
|
25
|
+
end.join
|
26
|
+
end.call{ break } # rubocop:disable Style/MultilineBlockChain
|
20
27
|
'can not handle break in thread'
|
21
28
|
rescue LocalJumpError
|
22
29
|
false
|
@@ -140,6 +147,13 @@ describe InThreads do
|
|
140
147
|
end
|
141
148
|
|
142
149
|
describe 'exception/break handling' do
|
150
|
+
it 'returns identical to each when initialized with block', :skip => SKIP_IF_BREAK_IN_THREAD_IS_IGNORED do
|
151
|
+
v = double
|
152
|
+
expect(enum.each{ break v }).to eq(v) # rubocop:disable Lint/UnreachableLoop
|
153
|
+
expect(enum.in_threads{ break v }).to eq(v)
|
154
|
+
expect(enum.in_threads.each{ break v }).to eq(v) # rubocop:disable Lint/UnreachableLoop
|
155
|
+
end
|
156
|
+
|
143
157
|
%w[each map all?].each do |method|
|
144
158
|
describe "for ##{method}" do
|
145
159
|
it 'passes exception raised in block' do
|
@@ -151,7 +165,7 @@ describe InThreads do
|
|
151
165
|
fail 'expected'
|
152
166
|
end
|
153
167
|
|
154
|
-
expect{ enum.in_threads.send(method){} }.to raise_error('expected')
|
168
|
+
expect{ enum.in_threads.send(method){ nil } }.to raise_error('expected')
|
155
169
|
end
|
156
170
|
|
157
171
|
it 'handles break', :skip => SKIP_IF_BREAK_IN_THREAD_IS_IGNORED do
|
@@ -203,15 +217,18 @@ describe InThreads do
|
|
203
217
|
context 'exception order' do
|
204
218
|
before do
|
205
219
|
stub_const('Order', Queue.new)
|
220
|
+
def Order.releasing
|
221
|
+
fail 'expected'
|
222
|
+
ensure
|
223
|
+
push nil
|
224
|
+
end
|
206
225
|
end
|
207
226
|
|
208
227
|
it 'passes exception raised during iteration if it happens earlier than in block' do
|
209
228
|
def enum.each(&block)
|
210
229
|
5.times(&block)
|
211
|
-
|
230
|
+
Order.releasing do
|
212
231
|
fail 'expected'
|
213
|
-
ensure
|
214
|
-
Order.push nil
|
215
232
|
end
|
216
233
|
end
|
217
234
|
|
@@ -234,10 +251,8 @@ describe InThreads do
|
|
234
251
|
|
235
252
|
expect do
|
236
253
|
enum.in_threads(10).send(method) do
|
237
|
-
|
254
|
+
Order.releasing do
|
238
255
|
fail 'expected'
|
239
|
-
ensure
|
240
|
-
Order.push nil
|
241
256
|
end
|
242
257
|
end
|
243
258
|
end.to raise_error('expected')
|
@@ -247,10 +262,8 @@ describe InThreads do
|
|
247
262
|
expect do
|
248
263
|
enum.in_threads(10).send(method) do |i|
|
249
264
|
if i == 5
|
250
|
-
|
265
|
+
Order.releasing do
|
251
266
|
fail 'expected'
|
252
|
-
ensure
|
253
|
-
Order.push nil
|
254
267
|
end
|
255
268
|
else
|
256
269
|
Thread.pass while Order.empty?
|
@@ -509,8 +522,13 @@ describe InThreads do
|
|
509
522
|
collect map
|
510
523
|
group_by max_by min_by minmax_by sort_by
|
511
524
|
sum uniq
|
525
|
+
to_h to_set
|
512
526
|
].each do |method|
|
527
|
+
next if method == 'to_h' && InThreads::INCOMPATIBLE_METHODS.include?(:to_h)
|
528
|
+
|
513
529
|
describe_enum_method method do
|
530
|
+
let(:value_proc){ proc{ [rand] * 2 } } if method == 'to_h'
|
531
|
+
|
514
532
|
it 'returns same result with threads' do
|
515
533
|
expect(enum.in_threads.send(method, &:compute)).
|
516
534
|
to eq(enum.send(method, &:compute))
|
@@ -716,6 +734,34 @@ describe InThreads do
|
|
716
734
|
end
|
717
735
|
end
|
718
736
|
end
|
737
|
+
|
738
|
+
describe_enum_method :each_with_object do
|
739
|
+
let(:block) do
|
740
|
+
proc do |o, h|
|
741
|
+
v = o.compute
|
742
|
+
mutex.synchronize{ h[v] = true }
|
743
|
+
end
|
744
|
+
end
|
745
|
+
|
746
|
+
it 'returns same result with threads' do
|
747
|
+
expect(enum.in_threads.each_with_object({}, &block)).
|
748
|
+
to eq(enum.each_with_object({}, &block))
|
749
|
+
end
|
750
|
+
|
751
|
+
it 'yields same objects' do
|
752
|
+
yielded = []
|
753
|
+
enum.in_threads.each_with_object({}) do |o, _h|
|
754
|
+
mutex.synchronize{ yielded << o }
|
755
|
+
o.compute
|
756
|
+
end
|
757
|
+
expect(yielded).to match_array(items)
|
758
|
+
end
|
759
|
+
|
760
|
+
it 'runs faster with threads', :flaky do
|
761
|
+
expect{ enum.in_threads.each_with_object({}, &block) }.
|
762
|
+
to be_faster_than{ enum.each_with_object({}, &block) }
|
763
|
+
end
|
764
|
+
end
|
719
765
|
end
|
720
766
|
|
721
767
|
context 'unthreaded' do
|
@@ -774,14 +820,6 @@ describe InThreads do
|
|
774
820
|
end
|
775
821
|
end
|
776
822
|
|
777
|
-
describe_enum_method :each_with_object do
|
778
|
-
let(:block){ proc{ |o, h| h[o] = true } }
|
779
|
-
|
780
|
-
it 'returns same result' do
|
781
|
-
expect(enum.in_threads.each_with_object({}, &block)).to eq(enum.each_with_object({}, &block))
|
782
|
-
end
|
783
|
-
end
|
784
|
-
|
785
823
|
%w[chunk slice_before slice_after].each do |method|
|
786
824
|
describe_enum_method method do
|
787
825
|
it 'returns same result' do
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: in_threads
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ivan Kuchin
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2022-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -44,23 +44,44 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
47
|
+
version: '1.22'
|
48
|
+
- - "!="
|
49
|
+
- !ruby/object:Gem::Version
|
50
|
+
version: 1.22.2
|
51
|
+
type: :development
|
52
|
+
prerelease: false
|
53
|
+
version_requirements: !ruby/object:Gem::Requirement
|
54
|
+
requirements:
|
55
|
+
- - "~>"
|
56
|
+
- !ruby/object:Gem::Version
|
57
|
+
version: '1.22'
|
58
|
+
- - "!="
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.22.2
|
61
|
+
- !ruby/object:Gem::Dependency
|
62
|
+
name: rubocop-rspec
|
63
|
+
requirement: !ruby/object:Gem::Requirement
|
64
|
+
requirements:
|
65
|
+
- - "~>"
|
66
|
+
- !ruby/object:Gem::Version
|
67
|
+
version: '2.0'
|
48
68
|
type: :development
|
49
69
|
prerelease: false
|
50
70
|
version_requirements: !ruby/object:Gem::Requirement
|
51
71
|
requirements:
|
52
72
|
- - "~>"
|
53
73
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0
|
55
|
-
description:
|
56
|
-
email:
|
74
|
+
version: '2.0'
|
75
|
+
description:
|
76
|
+
email:
|
57
77
|
executables: []
|
58
78
|
extensions: []
|
59
79
|
extra_rdoc_files: []
|
60
80
|
files:
|
81
|
+
- ".github/workflows/check.yml"
|
82
|
+
- ".github/workflows/rubocop.yml"
|
61
83
|
- ".gitignore"
|
62
84
|
- ".rubocop.yml"
|
63
|
-
- ".travis.yml"
|
64
85
|
- CHANGELOG.markdown
|
65
86
|
- Gemfile
|
66
87
|
- LICENSE.txt
|
@@ -68,15 +89,15 @@ files:
|
|
68
89
|
- in_threads.gemspec
|
69
90
|
- lib/in_threads.rb
|
70
91
|
- spec/in_threads_spec.rb
|
71
|
-
homepage:
|
92
|
+
homepage: https://github.com/toy/in_threads
|
72
93
|
licenses:
|
73
94
|
- MIT
|
74
95
|
metadata:
|
75
96
|
bug_tracker_uri: https://github.com/toy/in_threads/issues
|
76
97
|
changelog_uri: https://github.com/toy/in_threads/blob/master/CHANGELOG.markdown
|
77
|
-
documentation_uri: https://www.rubydoc.info/gems/in_threads/1.
|
98
|
+
documentation_uri: https://www.rubydoc.info/gems/in_threads/1.6.0
|
78
99
|
source_code_uri: https://github.com/toy/in_threads
|
79
|
-
post_install_message:
|
100
|
+
post_install_message:
|
80
101
|
rdoc_options: []
|
81
102
|
require_paths:
|
82
103
|
- lib
|
@@ -91,8 +112,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
112
|
- !ruby/object:Gem::Version
|
92
113
|
version: '0'
|
93
114
|
requirements: []
|
94
|
-
rubygems_version: 3.
|
95
|
-
signing_key:
|
115
|
+
rubygems_version: 3.3.5
|
116
|
+
signing_key:
|
96
117
|
specification_version: 4
|
97
118
|
summary: Run all possible enumerable methods in concurrent/parallel threads
|
98
119
|
test_files:
|
data/.travis.yml
DELETED
@@ -1,30 +0,0 @@
|
|
1
|
-
sudo: false
|
2
|
-
language: ruby
|
3
|
-
rvm:
|
4
|
-
- '1.8.7-p371'
|
5
|
-
- '1.9.3-p551'
|
6
|
-
- '2.0.0-p648'
|
7
|
-
- '2.1.10'
|
8
|
-
- '2.2.10'
|
9
|
-
- '2.3.8'
|
10
|
-
- '2.4.5'
|
11
|
-
- '2.5.3'
|
12
|
-
- '2.6.0'
|
13
|
-
- 'ruby-head'
|
14
|
-
- 'jruby-9.0.5.0'
|
15
|
-
- 'jruby-9.1.9.0'
|
16
|
-
before_install:
|
17
|
-
- gem install bundler
|
18
|
-
- ruby -e 'require "rubygems"; require "bundler/inline"; gemfile{ source "https://rubygems.org"; gem "rubygems-update" }' # get compatible version of rubygems-update
|
19
|
-
- gem update --system
|
20
|
-
script: bundle exec rspec
|
21
|
-
matrix:
|
22
|
-
include:
|
23
|
-
- env: RUBOCOP=✓
|
24
|
-
rvm: '2.5.3'
|
25
|
-
script: bundle exec rubocop
|
26
|
-
- env: CHECK_RUBIES=✓
|
27
|
-
rvm: '2.5.3'
|
28
|
-
script: bundle exec travis_check_rubies
|
29
|
-
allow_failures:
|
30
|
-
- rvm: 'ruby-head'
|