concurrent-enumerable 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: b71e49425a4a524961128fa383bf319a58fe45c6
4
+ data.tar.gz: f620d882c9b5a35c40eefc82ca003dae94dcc0c1
5
+ SHA512:
6
+ metadata.gz: 57254b26ad28fcf85350f75a10dd7025b95ad664dfdfae3f7d4b0ee0ed48c206eb2158121a8b9e64aafac6ec8db2e447210ad24607e0efb6de07c7f38fd2547d
7
+ data.tar.gz: 34c26ea94f43045885c1a4e1b33c0ef9c155d1da653dd6357f433009c55c8d252cd3ed93c4ae408966250b64424594c49a698deab4b950aa96ce829fff7ff8a0
@@ -0,0 +1,16 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .ruby-gemset
16
+ .ruby-version
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --require spec_helper
@@ -0,0 +1,14 @@
1
+ AllCops:
2
+ Exclude:
3
+ - concurrent-enumerable.gemspec
4
+ - lib/concurrent-enumerable.rb
5
+
6
+ Documentation:
7
+ Enabled: false
8
+
9
+ Eval:
10
+ Exclude:
11
+ - spec/spec_helper.rb
12
+
13
+ MethodLength:
14
+ Max: 20
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in concurrent_enumerable.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Sebastian Edwards
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,31 @@
1
+ # ConcurrentEnumerable
2
+
3
+ TODO: Write a gem description
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'concurrent_enumerable'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install concurrent_enumerable
20
+
21
+ ## Usage
22
+
23
+ TODO: Write usage instructions here
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it ( https://github.com/[my-github-username]/concurrent_enumerable/fork )
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create a new Pull Request
@@ -0,0 +1 @@
1
+ require 'bundler/gem_tasks'
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'concurrent_enumerable/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'concurrent-enumerable'
8
+ spec.version = ConcurrentEnumerable::VERSION
9
+ spec.authors = ['Sebastian Edwards']
10
+ spec.email = ['me@sebastianedwards.co.nz']
11
+ spec.summary = 'Run enumerable operations in parallel'
12
+ spec.description = ''
13
+ spec.homepage = ''
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_development_dependency 'bundler', '~> 1.7'
22
+ spec.add_development_dependency 'rake', '~> 10.0'
23
+ spec.add_development_dependency 'rspec', '~> 3.0'
24
+
25
+ spec.add_runtime_dependency 'concurrent-ruby', '~> 0.8.0'
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'concurrent'
2
+ require 'delegate'
3
+
4
+ require 'concurrent_enumerable/core_ext'
5
+ require 'concurrent_enumerable/enumerable_interface'
6
+ require 'concurrent_enumerable/parallel'
7
+ require 'concurrent_enumerable/version'
8
+
9
+ module ConcurrentEnumerable; end
@@ -0,0 +1,9 @@
1
+ module Enumerable
2
+ def parallel(opts = {})
3
+ ConcurrentEnumerable::Parallel.new(self, opts)
4
+ end
5
+
6
+ def serial
7
+ self
8
+ end
9
+ end
@@ -0,0 +1,35 @@
1
+ module ConcurrentEnumerable
2
+ module EnumerableInterface
3
+ module_function
4
+
5
+ def use(runner, methods)
6
+ enumerable_methods = Enumerable.instance_methods.map(&:to_s)
7
+ enumerable_methods << 'each'
8
+ methods.each do |method|
9
+ next unless enumerable_methods.include?(method)
10
+ class_eval <<-RUBY
11
+ def #{method}(*args, &block)
12
+ #{runner}(:#{method}, *args, &block)
13
+ end
14
+ RUBY
15
+ end
16
+ end
17
+
18
+ private :use
19
+
20
+ use :run_in_threads, %w(
21
+ all? any? count detect find find_index max_by min_by minmax_by none?
22
+ one? partition
23
+ )
24
+
25
+ use :run_in_threads_return_original, %w(
26
+ cycle each each_cons each_entry each_slice each_with_index enum_cons
27
+ enum_slice enum_with_index reverse_each zip
28
+ )
29
+
30
+ use :run_in_threads_return_parallel, %w(
31
+ collect collect_concat drop_while find_all flat_map grep group_by map
32
+ reject select sort sort_by take_while zip
33
+ )
34
+ end
35
+ end
@@ -0,0 +1,58 @@
1
+ module ConcurrentEnumerable
2
+ class Parallel < SimpleDelegator
3
+ include EnumerableInterface
4
+
5
+ protected :__getobj__, :__setobj__
6
+
7
+ def initialize(list, opts = {})
8
+ super list
9
+ @opts = opts
10
+ @executor = Concurrent::OptionsParser.get_executor_from(opts) || \
11
+ Concurrent.configuration.global_task_pool
12
+ end
13
+
14
+ def parallel
15
+ self
16
+ end
17
+
18
+ def serial
19
+ __getobj__
20
+ end
21
+
22
+ protected
23
+
24
+ def run_in_threads(method, *args, &block)
25
+ if block
26
+ latch = Concurrent::CountDownLatch.new(size)
27
+
28
+ results = Array.new(size)
29
+
30
+ index = Concurrent::AtomicFixnum.new(-1)
31
+
32
+ __getobj__.each do |item|
33
+ i = index.increment
34
+
35
+ @executor.post do
36
+ results[i] = yield(item)
37
+ latch.count_down
38
+ end
39
+ end
40
+
41
+ latch.wait
42
+ results.send(method, *args) { |value| value }
43
+ else
44
+ send method, *args
45
+ end
46
+ end
47
+
48
+ def run_in_threads_return_original(method, *args, &block)
49
+ run_in_threads(method, *args, &block)
50
+
51
+ self
52
+ end
53
+
54
+ def run_in_threads_return_parallel(method, *args, &block)
55
+ Parallel.new run_in_threads(method, *args, &block), @opts
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,3 @@
1
+ module ConcurrentEnumerable
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,7 @@
1
+ RSpec.describe Enumerable do
2
+ describe '#parallel' do
3
+ it 'should return a parallel instance' do
4
+ expect([].parallel).to be_a Parallel
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,65 @@
1
+ require 'benchmark'
2
+
3
+ RSpec.describe Parallel do
4
+ describe '#any? (parallelizable, value-returning)' do
5
+ it 'should produce the correct result' do
6
+ result = Parallel.new([1, 2, 3]).any? { |x| x == 3 }
7
+
8
+ expect(result).to be_truthy
9
+ end
10
+
11
+ it 'should run given block in parallel' do
12
+ time = Benchmark.measure do
13
+ Parallel.new([1, 2, 3]).any? { sleep 0.1 }
14
+ end
15
+
16
+ expect(time.real).to be < 0.2
17
+ end
18
+ end
19
+
20
+ describe '#each (parallelizable, self-returning)' do
21
+ it 'should produce the correct result' do
22
+ result = Parallel.new([1, 2, 3]).each { |x| x * 2 }
23
+
24
+ expect(result).to eq [1, 2, 3]
25
+ end
26
+
27
+ it 'should run given block in parallel' do
28
+ time = Benchmark.measure do
29
+ Parallel.new([1, 2, 3]).each { sleep 0.1 }
30
+ end
31
+
32
+ expect(time.real).to be < 0.2
33
+ end
34
+ end
35
+
36
+ describe '#map (parallelizable, Parallel-returning)' do
37
+ it 'should produce the correct result' do
38
+ result = Parallel.new([1, 2, 3]).map { |x| x * 2 }
39
+
40
+ expect(result).to eq [2, 4, 6]
41
+ end
42
+
43
+ it 'should run given block in parallel' do
44
+ time = Benchmark.measure do
45
+ Parallel.new([1, 2, 3]).map { sleep 0.1 }
46
+ end
47
+
48
+ expect(time.real).to be < 0.2
49
+ end
50
+
51
+ it 'should return a Parallel' do
52
+ result = Parallel.new([1, 2, 3]).map { |x| x * 2 }
53
+
54
+ expect(result).to be_a Parallel
55
+ end
56
+ end
57
+
58
+ describe '#reduce (non-parallelizable)' do
59
+ it 'should produce the correct result' do
60
+ result = Parallel.new([1, 2, 3]).reduce { |a, e| a + e }
61
+
62
+ expect(result).to eq 6
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,18 @@
1
+ RSpec.configure do |config|
2
+ config.disable_monkey_patching!
3
+ config.order = :random
4
+
5
+ config.expect_with :rspec do |expectations|
6
+ expectations.include_chain_clauses_in_custom_matcher_descriptions = true
7
+ end
8
+
9
+ config.mock_with :rspec do |mocks|
10
+ mocks.verify_partial_doubles = true
11
+ end
12
+ end
13
+
14
+ require 'concurrent-enumerable'
15
+
16
+ ConcurrentEnumerable.constants.each do |const|
17
+ eval "#{const} = ConcurrentEnumerable::#{const}"
18
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: concurrent-enumerable
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Sebastian Edwards
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-02-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: concurrent-ruby
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.8.0
69
+ description: ''
70
+ email:
71
+ - me@sebastianedwards.co.nz
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".rubocop.yml"
79
+ - Gemfile
80
+ - LICENSE.txt
81
+ - README.md
82
+ - Rakefile
83
+ - concurrent-enumerable.gemspec
84
+ - lib/concurrent-enumerable.rb
85
+ - lib/concurrent_enumerable/core_ext.rb
86
+ - lib/concurrent_enumerable/enumerable_interface.rb
87
+ - lib/concurrent_enumerable/parallel.rb
88
+ - lib/concurrent_enumerable/version.rb
89
+ - spec/lib/concurrent_enumerable/core_ext_spec.rb
90
+ - spec/lib/concurrent_enumerable/parallel_spec.rb
91
+ - spec/spec_helper.rb
92
+ homepage: ''
93
+ licenses:
94
+ - MIT
95
+ metadata: {}
96
+ post_install_message:
97
+ rdoc_options: []
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ required_rubygems_version: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - ">="
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ requirements: []
111
+ rubyforge_project:
112
+ rubygems_version: 2.4.5
113
+ signing_key:
114
+ specification_version: 4
115
+ summary: Run enumerable operations in parallel
116
+ test_files:
117
+ - spec/lib/concurrent_enumerable/core_ext_spec.rb
118
+ - spec/lib/concurrent_enumerable/parallel_spec.rb
119
+ - spec/spec_helper.rb