in_threads 0.0.4 → 1.0.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.
data/.gitignore ADDED
@@ -0,0 +1,11 @@
1
+ /pkg/
2
+
3
+ /doc/
4
+ /rdoc/
5
+ /.yardoc/
6
+ /coverage/
7
+
8
+ Makefile
9
+ *.o
10
+ *.bundle
11
+ /tmp/
data/LICENSE.txt CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Ivan Kuchin
1
+ Copyright (c) 2010-2011 Ivan Kuchin
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.markdown CHANGED
@@ -1,42 +1,35 @@
1
- # progress
1
+ # in_threads
2
2
 
3
- http://github.com/toy/in_threads
3
+ Easily execute ruby code in parallel.
4
4
 
5
- ## DESCRIPTION:
5
+ ## Installation
6
6
 
7
- Easily execute ruby code in parallel
7
+ gem install in_threads
8
8
 
9
- ## SYNOPSIS:
9
+ ## Usage
10
10
 
11
11
  By default there is maximum of 10 simultaneous threads
12
12
 
13
- urls.in_threads.each do |url|
14
- url.save_to_disk
15
- end
16
-
17
13
  urls.in_threads.map do |url|
18
14
  url.fetch
19
15
  end
20
16
 
17
+ urls.in_threads.each do |url|
18
+ url.save_to_disk
19
+ end
20
+
21
21
  numbers.in_threads(2).map do |number|
22
-
23
22
  # whery long and complicated formula
24
23
  # using only 2 threads
25
24
  end
26
25
 
27
- You can use any Enumerable method but it is up to you if this is good
26
+ You can use any Enumerable method, but some of them can not use threads (`inject`, `reduce`) or don't use blocks (`to_a`, `entries`, `drop`, `take`, `first`, `include?`, `member?`) or have both problems depending on usage type (`min`, `max`, `minmax`, `sort`)
28
27
 
29
28
  urls.in_threads.any?(&:ok?)
30
29
  urls.in_threads.all?(&:ok?)
31
-
32
- ## REQUIREMENTS:
33
-
34
- ruby )))
35
-
36
- ## INSTALL:
37
-
38
- sudo gem install in_threads
30
+ urls.in_threads.none?(&:error?)
31
+ urls.in_threads.grep(/example\.com/, &:fetch)
39
32
 
40
33
  ## Copyright
41
34
 
42
- Copyright (c) 2010 Ivan Kuchin. See LICENSE.txt for details.
35
+ Copyright (c) 2010-2011 Ivan Kuchin. See LICENSE.txt for details.
data/in_threads.gemspec CHANGED
@@ -1,57 +1,19 @@
1
- # Generated by jeweler
2
- # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
- # -*- encoding: utf-8 -*-
1
+ # encoding: UTF-8
5
2
 
6
3
  Gem::Specification.new do |s|
7
- s.name = %q{in_threads}
8
- s.version = "0.0.4"
4
+ s.name = 'in_threads'
5
+ s.version = '1.0.0'
6
+ s.summary = %q{Execute ruby code in parallel}
7
+ s.homepage = "http://github.com/toy/#{s.name}"
8
+ s.authors = ['Ivan Kuchin']
9
+ s.license = 'MIT'
9
10
 
10
- s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Ivan Kuchin"]
12
- s.date = %q{2010-12-15}
13
- s.extra_rdoc_files = [
14
- "LICENSE.txt",
15
- "README.markdown"
16
- ]
17
- s.files = [
18
- ".tmignore",
19
- "LICENSE.txt",
20
- "README.markdown",
21
- "Rakefile",
22
- "VERSION",
23
- "in_threads.gemspec",
24
- "lib/in_threads.rb",
25
- "spec/in_threads_spec.rb",
26
- "spec/spec_helper.rb"
27
- ]
28
- s.homepage = %q{http://github.com/toy/in_threads}
29
- s.licenses = ["MIT"]
30
- s.require_paths = ["lib"]
31
- s.rubygems_version = %q{1.3.7}
32
- s.summary = %q{Execute ruby blocks in parallel}
33
- s.test_files = [
34
- "spec/in_threads_spec.rb",
35
- "spec/spec_helper.rb"
36
- ]
11
+ s.rubyforge_project = s.name
37
12
 
38
- if s.respond_to? :specification_version then
39
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
40
- s.specification_version = 3
13
+ s.files = `git ls-files`.split("\n")
14
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
15
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ s.require_paths = %w[lib]
41
17
 
42
- if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
43
- s.add_development_dependency(%q<jeweler>, ["~> 1.5.1"])
44
- s.add_development_dependency(%q<rake-gem-ghost>, [">= 0"])
45
- s.add_development_dependency(%q<rspec>, [">= 0"])
46
- else
47
- s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
48
- s.add_dependency(%q<rake-gem-ghost>, [">= 0"])
49
- s.add_dependency(%q<rspec>, [">= 0"])
50
- end
51
- else
52
- s.add_dependency(%q<jeweler>, ["~> 1.5.1"])
53
- s.add_dependency(%q<rake-gem-ghost>, [">= 0"])
54
- s.add_dependency(%q<rspec>, [">= 0"])
55
- end
18
+ s.add_development_dependency 'rspec'
56
19
  end
57
-
data/lib/in_threads.rb CHANGED
@@ -2,37 +2,137 @@ require 'thread'
2
2
  require 'thwait'
3
3
 
4
4
  module Enumerable
5
- def in_threads(max_threads = 10)
6
- InThreads.new(self, max_threads)
5
+ # Run enumerable method blocks in threads
6
+ def in_threads(thread_count = 10, &block)
7
+ InThreads.new(self, thread_count, &block)
7
8
  end
8
9
  end
9
10
 
11
+ # TODO: create my own ThreadsWait with blackjack and hookers?
12
+ # TODO: create class methods for connecting Enumerable method to runner
13
+ # TODO: run_in_threads_inconsecutive for `all?`, `any?`, `none?` and `one?`
14
+ # TODO: all ruby1.9.3 methods
15
+ # TODO: better way of handling grep?
16
+ # TODO: check method presence if Enumerable before connectin to runner
17
+
10
18
  class InThreads
11
- def initialize(object, max_threads)
12
- @threads = []
13
- @object = object
14
- @max_threads = max_threads
19
+ (
20
+ instance_methods.map(&:to_s) -
21
+ %w[__id__ __send__ class inspect instance_of? is_a? kind_of? nil? object_id respond_to? send]
22
+ ).each{ |name| undef_method name }
23
+ (private_instance_methods.map(&:to_s) - %w[initialize]).each{ |name| undef_method name }
24
+
25
+ attr_reader :enumerable, :thread_count
26
+ def initialize(enumerable, thread_count = 10, &block)
27
+ @enumerable, @thread_count = enumerable, thread_count
28
+ each(&block) if block
29
+ end
30
+
31
+ def in_threads(thread_count = 10, &block)
32
+ self.class.new(enumerable, thread_count, &block)
33
+ end
34
+
35
+ %w[
36
+ each
37
+ all? any? none? one?
38
+ detect find find_index drop_while take_while
39
+ partition find_all select reject count
40
+ collect map group_by max_by min_by minmax_by sort_by
41
+ ].each do |name|
42
+ class_eval <<-RUBY
43
+ def #{name}(*args, &block)
44
+ run_in_threads_consecutive(enumerable, :#{name}, *args, &block)
45
+ end
46
+ RUBY
47
+ end
48
+
49
+ %w[
50
+ reverse_each
51
+ each_with_index enum_with_index
52
+ each_cons each_slice enum_cons enum_slice
53
+ zip
54
+ cycle
55
+ ].each do |name|
56
+ class_eval <<-RUBY
57
+ def #{name}(*args, &block)
58
+ run_in_threads_block_result_irrelevant(enumerable, :#{name}, *args, &block)
59
+ end
60
+ RUBY
15
61
  end
16
62
 
17
- def map(*args, &block)
18
- run_in_threads(:map, *args, &block)
19
- @threads.map(&:value)
63
+ def grep(*args, &block)
64
+ if block
65
+ run_in_threads_consecutive(enumerable.grep(*args), :map, &block)
66
+ else
67
+ enumerable.grep(*args)
68
+ end
20
69
  end
21
70
 
22
- def method_missing(method, *args, &block)
23
- run_in_threads(method, *args, &block)
71
+ %w[
72
+ inject reduce
73
+ max min minmax sort
74
+ entries to_a
75
+ drop take
76
+ first
77
+ include? member?
78
+ ].each do |name|
79
+ class_eval <<-RUBY
80
+ def #{name}(*args, &block)
81
+ enumerable.#{name}(*args, &block)
82
+ end
83
+ RUBY
24
84
  end
25
85
 
26
86
  private
27
87
 
28
- def run_in_threads(method, *args, &block)
29
- @object.send(method, *args) do |*args|
30
- while @threads.count(&:alive?) >= @max_threads
31
- ThreadsWait.new(*@threads).next_wait
88
+ def run_in_threads_block_result_irrelevant(enumerable, method, *args, &block)
89
+ if block
90
+ waiter = ThreadsWait.new
91
+ begin
92
+ enumerable.send(method, *args) do |*block_args|
93
+ waiter.next_wait if waiter.threads.length >= thread_count
94
+ waiter.join_nowait([Thread.new(*block_args, &block)])
95
+ end
96
+ ensure
97
+ waiter.all_waits
98
+ end
99
+ else
100
+ enumerable.send(method, *args)
101
+ end
102
+ end
103
+
104
+ def run_in_threads_consecutive(enumerable, method, *args, &block)
105
+ if block
106
+ begin
107
+ queue = Queue.new
108
+ runner = Thread.new(enumerable) do |enumerable|
109
+ threads = []
110
+ begin
111
+ enumerable.each do |object|
112
+ if threads.length >= thread_count
113
+ threads = threads.select(&:alive?)
114
+ if threads.length >= thread_count
115
+ ThreadsWait.new(*threads).next_wait
116
+ end
117
+ end
118
+ break if Thread.current[:stop]
119
+ thread = Thread.new(object, &block)
120
+ threads << thread
121
+ queue << thread
122
+ end
123
+ ensure
124
+ threads.map(&:join)
125
+ end
126
+ end
127
+ enumerable.send(method, *args) do |*block_args|
128
+ queue.pop.value
129
+ end
130
+ ensure
131
+ runner[:stop] = true
132
+ runner.join
32
133
  end
33
- @threads << Thread.new(*args, &block)
134
+ else
135
+ enumerable.send(method, *args)
34
136
  end
35
- ensure
36
- @threads.map(&:join)
37
137
  end
38
138
  end
@@ -1,57 +1,355 @@
1
1
  require File.dirname(__FILE__) + '/spec_helper.rb'
2
2
 
3
- describe InThreads do
4
- before :each do
5
- srand 1
6
- @a = (1..30).map{ |i| mock(:"e#{i}", :hello => nil, :value => i, :rand => rand * 0.01) }
7
- @sleepy_prock = proc{ |e| sleep(e.rand); e.hello; e.value }
8
- @sleepy_prock_a = proc{ |e| sleep(e.inject{ |sum, e| e.rand }); e.hash }
3
+ class Item
4
+ def initialize(i)
5
+ @i, @rand = i, rand
9
6
  end
10
7
 
8
+ class MiddleMatcher
9
+ def ===(item)
10
+ raise "#{item.inspect} is not an Item" unless item.is_a?(Item)
11
+ (0.25..0.75) === item.instance_variable_get(:@rand)
12
+ end
13
+ end
14
+
15
+ def work
16
+ sleep @rand * 0.008
17
+ end
18
+
19
+ def value
20
+ work; @rand
21
+ end
22
+
23
+ def check?
24
+ value < 0.5
25
+ end
26
+
27
+ def touch_n_value(*args)
28
+ touch(*args); value
29
+ end
30
+
31
+ def touch_n_check?(*args)
32
+ touch(*args); check?
33
+ end
34
+ end
35
+
36
+ class ValueItem < Item
37
+ def initialize(i, value)
38
+ super(i)
39
+ @value = value
40
+ end
41
+
42
+ def value
43
+ work; @value
44
+ end
45
+
46
+ def check?
47
+ !!value
48
+ end
49
+ end
50
+
51
+ def enum_methods(methods)
52
+ (Enumerable.instance_methods.map(&:to_s) & methods)
53
+ end
54
+
55
+ describe "in_threads" do
56
+ let(:enum){ 30.times.map{ |i| Item.new(i) } }
57
+ let(:speed_coef){ 0.666 } # small coefficient, should be more if sleep time coefficient is bigger
58
+
11
59
  def measure
12
60
  start = Time.now
13
61
  yield
14
62
  Time.now - start
15
63
  end
16
64
 
17
- it "should execute block for each element" do
18
- @a.each{ |e| e.should_receive(:hello) }
19
- @a.in_threads.each(&:hello)
65
+ describe "in_threads" do
66
+ it "should not change existing instance" do
67
+ threaded = enum.in_threads(10)
68
+ proc{ threaded.in_threads(20) }.should_not change(threaded, :thread_count)
69
+ end
70
+
71
+ it "should create new instance with different title when called on WithProgress" do
72
+ threaded = enum.in_threads(10)
73
+ tthreaded = threaded.in_threads(20)
74
+ threaded.thread_count.should == 10
75
+ tthreaded.thread_count.should == 20
76
+ tthreaded.class.should == threaded.class
77
+ tthreaded.object_id.should_not == threaded.object_id
78
+ tthreaded.enumerable.should == threaded.enumerable
79
+ end
20
80
  end
21
81
 
22
- it "should not run simulanteously more threads" do
23
- @mutex = Mutex.new
24
- @threads = 0
25
- (1..100).to_a.in_threads(10).each do |i|
26
- (0..10).include?(@threads).should be_true
27
- @mutex.synchronize{ @threads += 1 }
28
- (0..10).include?(@threads).should be_true
29
- sleep 1 + rand * 1
30
- (0..10).include?(@threads).should be_true
31
- @mutex.synchronize{ @threads -= 1 }
32
- (0..10).include?(@threads).should be_true
82
+ describe "each" do
83
+ it "should return same enum after running" do
84
+ enum.in_threads.each(&:value).should == enum
85
+ end
86
+
87
+ it "should execute block for each element" do
88
+ enum.each{ |o| o.should_receive(:touch).once }
89
+ enum.in_threads.each(&:touch)
90
+ end
91
+
92
+ it "should run faster with threads" do
93
+ measure{ enum.in_threads.each(&:work) }.should < measure{ enum.each(&:work) } * speed_coef
94
+ end
95
+
96
+ it "should run faster with more threads" do
97
+ measure{ enum.in_threads(20).each(&:work) }.should < measure{ enum.in_threads(2).each(&:work) } * speed_coef
98
+ end
99
+
100
+ it "should return same enum without block" do
101
+ enum.in_threads.each.to_a.should == enum.each.to_a
33
102
  end
34
103
  end
35
104
 
36
- it "should run faster than without threads" do
37
- (measure{ @a.in_threads.each(&@sleepy_prock) } * 2).should be < measure{ @a.each(&@sleepy_prock) }
105
+ enum_methods(%w[each_with_index enum_with_index]).each do |method|
106
+ describe method do
107
+ let(:runner){ proc{ |o, i| o.value } }
108
+
109
+ it "should return same result with threads" do
110
+ enum.in_threads.send(method, &runner).should == enum.send(method, &runner)
111
+ end
112
+
113
+ it "should fire same objects" do
114
+ enum.send(method){ |o, i| o.should_receive(:touch).with(i).once }
115
+ enum.in_threads.send(method){ |o, i| o.touch_n_value(i) }
116
+ end
117
+
118
+ it "should run faster with threads" do
119
+ measure{ enum.in_threads.send(method, &runner) }.should < measure{ enum.send(method, &runner) } * speed_coef
120
+ end
121
+
122
+ it "should return same enum without block" do
123
+ enum.in_threads.send(method).to_a.should == enum.send(method).to_a
124
+ end
125
+ end
38
126
  end
39
127
 
40
- it "should run not much slower than max of block running times if ran simultaneously" do
41
- measure{ (1..95).in_threads(100).each{ |i| sleep(i * 0.01) } }.should be < 1.0
128
+ describe "reverse_each" do
129
+ it "should return same result with threads" do
130
+ enum.in_threads.reverse_each(&:value).should == enum.reverse_each(&:value)
131
+ end
132
+
133
+ it "should fire same objects in reverse order" do
134
+ @order = mock('order', :touch => nil)
135
+ @order.should_receive(:touch).with(enum.last).ordered
136
+ @order.should_receive(:touch).with(enum[enum.length / 2]).ordered
137
+ @order.should_receive(:touch).with(enum.first).ordered
138
+ enum.reverse_each{ |o| o.should_receive(:touch).once }
139
+ @mutex = Mutex.new
140
+ enum.in_threads.reverse_each do |o|
141
+ @mutex.synchronize{ @order.touch(o) }
142
+ o.touch_n_value
143
+ end
144
+ end
145
+
146
+ it "should run faster with threads" do
147
+ measure{ enum.in_threads.reverse_each(&:value) }.should < measure{ enum.reverse_each(&:value) } * speed_coef
148
+ end
149
+
150
+ it "should return same enum without block" do
151
+ enum.in_threads.reverse_each.to_a.should == enum.reverse_each.to_a
152
+ end
42
153
  end
43
154
 
44
- it "should run faster when ran with more threads" do
45
- (measure{ @a.in_threads(20).each(&@sleepy_prock) } * 2).should be < measure{ @a.in_threads(2).each(&@sleepy_prock) }
155
+ %w[
156
+ all? any? none? one?
157
+ detect find find_index drop_while take_while
158
+ ].each do |method|
159
+ describe method do
160
+ let(:enum){ 100.times.map{ |i| ValueItem.new(i, i % 2 == 1) } }
161
+
162
+ it "should return same result with threads" do
163
+ enum.in_threads.send(method, &:check?).should == enum.send(method, &:check?)
164
+ end
165
+
166
+ it "should fire same objects but not all" do
167
+ a = []
168
+ enum.send(method) do |o|
169
+ a << o
170
+ o.check?
171
+ end
172
+
173
+ @a = []
174
+ @mutex = Mutex.new
175
+ enum.in_threads.send(method){ |o| @mutex.synchronize{ @a << o }; o.check? }
176
+
177
+ @a.length.should >= a.length
178
+ @a.length.should <= enum.length / 2
179
+ end
180
+
181
+ it "should run faster with threads" do
182
+ value = %w[all? drop_while take_while].include?(method)
183
+ enum = 30.times.map{ |i| ValueItem.new(i, value) }
184
+ measure{ enum.in_threads.send(method, &:check?) }.should < measure{ enum.send(method, &:check?) } * speed_coef
185
+ end
186
+ end
46
187
  end
47
188
 
48
- %w(each map any? all? none?).each do |method|
49
- it "should return same as without thread for #{method}" do
50
- @a.in_threads.send(method, &@sleepy_prock).should == @a.send(method, &@sleepy_prock)
189
+ %w[partition find_all select reject count].each do |method|
190
+ describe method do
191
+ it "should return same result with threads" do
192
+ enum.in_threads.send(method, &:check?).should == enum.send(method, &:check?)
193
+ end
194
+
195
+ it "should fire same objects" do
196
+ enum.send(method){ |o| o.should_receive(:touch).once }
197
+ enum.in_threads.send(method, &:touch_n_check?)
198
+ end
199
+
200
+ it "should run faster with threads" do
201
+ measure{ enum.in_threads.send(method, &:check?) }.should < measure{ enum.send(method, &:check?) } * speed_coef
202
+ end
203
+ end
204
+ end
205
+
206
+ %w[collect map group_by max_by min_by minmax_by sort_by].each do |method|
207
+ describe method do
208
+ it "should return same result with threads" do
209
+ enum.in_threads.send(method, &:value).should == enum.send(method, &:value)
210
+ end
211
+
212
+ it "should fire same objects" do
213
+ enum.send(method){ |o| o.should_receive(:touch).once; 0 }
214
+ enum.in_threads.send(method, &:touch_n_value)
215
+ end
216
+
217
+ it "should run faster with threads" do
218
+ measure{ enum.in_threads.send(method, &:value) }.should < measure{ enum.send(method, &:value) } * speed_coef
219
+ end
220
+ end
221
+ end
222
+
223
+ enum_methods(%w[each_cons each_slice enum_slice enum_cons]).each do |method|
224
+ describe method do
225
+ let(:runner){ proc{ |a| a.each(&:value) } }
226
+
227
+ it "should fire same objects" do
228
+ enum.send(method, 3){ |a| a.first.should_receive(:touch).with(a).once }
229
+ enum.in_threads.send(method, 3){ |a| a.first.touch_n_value(a) }
230
+ end
231
+
232
+ it "should return same with block" do
233
+ enum.in_threads.send(method, 3, &runner).should == enum.send(method, 3, &runner)
234
+ end
235
+
236
+ it "should run faster with threads" do
237
+ measure{ enum.in_threads.send(method, 3, &runner) }.should < measure{ enum.send(method, 3, &runner) } * speed_coef
238
+ end
239
+
240
+ it "should return same without block" do
241
+ enum.in_threads.send(method, 3).to_a.should == enum.send(method, 3).to_a
242
+ end
243
+ end
244
+ end
245
+
246
+ describe "zip" do
247
+ let(:runner){ proc{ |a| a.each(&:value) } }
248
+
249
+ it "should fire same objects" do
250
+ enum.zip(enum, enum){ |a| a.first.should_receive(:touch).with(a).once }
251
+ enum.in_threads.zip(enum, enum){ |a| a.first.touch_n_value(a) }
252
+ end
253
+
254
+ it "should return same with block" do
255
+ enum.in_threads.zip(enum, enum, &runner).should == enum.zip(enum, enum, &runner)
256
+ end
257
+
258
+ it "should run faster with threads" do
259
+ measure{ enum.in_threads.zip(enum, enum, &runner) }.should < measure{ enum.zip(enum, enum, &runner) } * speed_coef
260
+ end
261
+
262
+ it "should return same without block" do
263
+ enum.in_threads.zip(enum, enum).should == enum.zip(enum, enum)
264
+ end
265
+ end
266
+
267
+ describe "cycle" do
268
+ it "should fire same objects" do
269
+ enum.cycle(1){ |o| o.should_receive(:touch).exactly(3).times }
270
+ enum.in_threads.cycle(3, &:touch_n_value)
271
+ end
272
+
273
+ it "should run faster with threads" do
274
+ measure{ enum.in_threads.cycle(3, &:work) }.should < measure{ enum.cycle(3, &:work) } * speed_coef
275
+ end
276
+
277
+ it "should return same enum without block" do
278
+ enum.in_threads.cycle(3).to_a.should == enum.cycle(3).to_a
279
+ end
280
+ end
281
+
282
+ describe "grep" do
283
+ let(:matcher){ Item::MiddleMatcher.new }
284
+
285
+ it "should fire same objects" do
286
+ enum.each{ |o| o.should_receive(:touch).exactly(matcher === o ? 1 : 0).times }
287
+ enum.in_threads.grep(matcher, &:touch_n_value)
288
+ end
289
+
290
+ it "should return same with block" do
291
+ enum.in_threads.grep(matcher, &:value).should == enum.grep(matcher, &:value)
292
+ end
293
+
294
+ it "should run faster with threads" do
295
+ measure{ enum.in_threads.grep(matcher, &:value) }.should < measure{ enum.grep(matcher, &:value) } * speed_coef
296
+ end
297
+
298
+ it "should return same without block" do
299
+ enum.in_threads.grep(matcher).should == enum.grep(matcher)
51
300
  end
52
301
  end
53
302
 
54
- it "should return same as without thread for .each_slice" do
55
- @a.in_threads.each_slice(2, &@sleepy_prock_a).should == @a.each_slice(2, &@sleepy_prock_a)
303
+ context "unthreaded" do
304
+ %w[inject reduce].each do |method|
305
+ describe method do
306
+ it "should return same result" do
307
+ combiner = proc{ |memo, o| memo + o.value }
308
+ enum.in_threads.send(method, 0, &combiner).should == enum.send(method, 0, &combiner)
309
+ end
310
+ end
311
+ end
312
+
313
+ %w[max min minmax sort].each do |method|
314
+ describe method do
315
+ it "should return same result" do
316
+ comparer = proc{ |a, b| a.value <=> b.value }
317
+ enum.in_threads.send(method, &comparer).should == enum.send(method, &comparer)
318
+ end
319
+ end
320
+ end
321
+
322
+ %w[to_a entries].each do |method|
323
+ describe method do
324
+ it "should return same result" do
325
+ enum.in_threads.send(method).should == enum.send(method)
326
+ end
327
+ end
328
+ end
329
+
330
+ %w[drop take].each do |method|
331
+ describe method do
332
+ it "should return same result" do
333
+ enum.in_threads.send(method, 2).should == enum.send(method, 2)
334
+ end
335
+ end
336
+ end
337
+
338
+ %w[first].each do |method|
339
+ describe method do
340
+ it "should return same result" do
341
+ enum.in_threads.send(method).should == enum.send(method)
342
+ enum.in_threads.send(method, 3).should == enum.send(method, 3)
343
+ end
344
+ end
345
+ end
346
+
347
+ %w[include? member?].each do |method|
348
+ describe method do
349
+ it "should return same result" do
350
+ enum.in_threads.send(method, enum[10]).should == enum.send(method, enum[10])
351
+ end
352
+ end
353
+ end
56
354
  end
57
355
  end
metadata CHANGED
@@ -2,12 +2,12 @@
2
2
  name: in_threads
3
3
  version: !ruby/object:Gem::Version
4
4
  hash: 23
5
- prerelease: false
5
+ prerelease:
6
6
  segments:
7
+ - 1
7
8
  - 0
8
9
  - 0
9
- - 4
10
- version: 0.0.4
10
+ version: 1.0.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Ivan Kuchin
@@ -15,43 +15,12 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-12-15 00:00:00 +03:00
19
- default_executable:
18
+ date: 2011-12-05 00:00:00 Z
20
19
  dependencies:
21
- - !ruby/object:Gem::Dependency
22
- name: jeweler
23
- prerelease: false
24
- requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
- requirements:
27
- - - ~>
28
- - !ruby/object:Gem::Version
29
- hash: 1
30
- segments:
31
- - 1
32
- - 5
33
- - 1
34
- version: 1.5.1
35
- type: :development
36
- version_requirements: *id001
37
- - !ruby/object:Gem::Dependency
38
- name: rake-gem-ghost
39
- prerelease: false
40
- requirement: &id002 !ruby/object:Gem::Requirement
41
- none: false
42
- requirements:
43
- - - ">="
44
- - !ruby/object:Gem::Version
45
- hash: 3
46
- segments:
47
- - 0
48
- version: "0"
49
- type: :development
50
- version_requirements: *id002
51
20
  - !ruby/object:Gem::Dependency
52
21
  name: rspec
53
22
  prerelease: false
54
- requirement: &id003 !ruby/object:Gem::Requirement
23
+ requirement: &id001 !ruby/object:Gem::Requirement
55
24
  none: false
56
25
  requirements:
57
26
  - - ">="
@@ -61,27 +30,23 @@ dependencies:
61
30
  - 0
62
31
  version: "0"
63
32
  type: :development
64
- version_requirements: *id003
33
+ version_requirements: *id001
65
34
  description:
66
35
  email:
67
36
  executables: []
68
37
 
69
38
  extensions: []
70
39
 
71
- extra_rdoc_files:
72
- - LICENSE.txt
73
- - README.markdown
40
+ extra_rdoc_files: []
41
+
74
42
  files:
75
- - .tmignore
43
+ - .gitignore
76
44
  - LICENSE.txt
77
45
  - README.markdown
78
- - Rakefile
79
- - VERSION
80
46
  - in_threads.gemspec
81
47
  - lib/in_threads.rb
82
48
  - spec/in_threads_spec.rb
83
49
  - spec/spec_helper.rb
84
- has_rdoc: true
85
50
  homepage: http://github.com/toy/in_threads
86
51
  licenses:
87
52
  - MIT
@@ -110,11 +75,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
110
75
  version: "0"
111
76
  requirements: []
112
77
 
113
- rubyforge_project:
114
- rubygems_version: 1.3.7
78
+ rubyforge_project: in_threads
79
+ rubygems_version: 1.8.11
115
80
  signing_key:
116
81
  specification_version: 3
117
- summary: Execute ruby blocks in parallel
82
+ summary: Execute ruby code in parallel
118
83
  test_files:
119
84
  - spec/in_threads_spec.rb
120
85
  - spec/spec_helper.rb
86
+ has_rdoc:
data/.tmignore DELETED
@@ -1 +0,0 @@
1
- /*.gemspec
data/Rakefile DELETED
@@ -1,25 +0,0 @@
1
- require 'rake'
2
- require 'jeweler'
3
- require 'rake/gem_ghost_task'
4
- require 'rspec/core/rake_task'
5
-
6
- name = 'in_threads'
7
-
8
- Jeweler::Tasks.new do |gem|
9
- gem.name = name
10
- gem.summary = %Q{Execute ruby blocks in parallel}
11
- gem.homepage = "http://github.com/toy/#{name}"
12
- gem.license = 'MIT'
13
- gem.authors = ['Ivan Kuchin']
14
- gem.add_development_dependency 'jeweler', '~> 1.5.1'
15
- gem.add_development_dependency 'rake-gem-ghost'
16
- gem.add_development_dependency 'rspec'
17
- end
18
- Jeweler::RubygemsDotOrgTasks.new
19
- Rake::GemGhostTask.new
20
-
21
- RSpec::Core::RakeTask.new(:spec) do |spec|
22
- spec.rspec_opts = ['--colour --format progress']
23
- spec.pattern = 'spec/**/*_spec.rb'
24
- end
25
- task :default => :spec
data/VERSION DELETED
@@ -1 +0,0 @@
1
- 0.0.4