parallizer 0.2.3 → 0.2.4

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/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parallizer (0.2.2)
4
+ parallizer (0.2.3)
5
5
  work_queue (~> 2.5.2)
6
6
 
7
7
  GEM
@@ -9,6 +9,7 @@ GEM
9
9
  specs:
10
10
  always_execute (0.1.3)
11
11
  diff-lcs (1.1.3)
12
+ rake (0.9.2.2)
12
13
  rspec (2.9.0)
13
14
  rspec-core (~> 2.9.0)
14
15
  rspec-expectations (~> 2.9.0)
@@ -25,4 +26,5 @@ PLATFORMS
25
26
  DEPENDENCIES
26
27
  always_execute (~> 0.1.1)
27
28
  parallizer!
29
+ rake
28
30
  rspec (~> 2.9.0)
@@ -0,0 +1,63 @@
1
+ require 'thread'
2
+
3
+ class Parallizer
4
+ # Initially taken from Celluloid. -mgp
5
+ module ThreadPool
6
+ THEAD_POOL_SIZE = 16
7
+
8
+ @pool = []
9
+ @mutex = Mutex.new
10
+
11
+ @max_idle = THEAD_POOL_SIZE
12
+
13
+ class << self
14
+ attr_accessor :max_idle
15
+
16
+ # Get a thread from the pool, running the given block
17
+ def get(&block)
18
+ @mutex.synchronize do
19
+ begin
20
+ if @pool.empty?
21
+ thread = create
22
+ else
23
+ thread = @pool.shift
24
+ end
25
+ end until thread.status # handle crashed threads
26
+
27
+ thread[:queue] << block
28
+ thread
29
+ end
30
+ end
31
+
32
+ # Return a thread to the pool
33
+ def put(thread)
34
+ @mutex.synchronize do
35
+ if @pool.size >= @max_idle
36
+ thread[:queue] << nil
37
+ else
38
+ @pool << thread
39
+ end
40
+ end
41
+ end
42
+
43
+ # Create a new thread with an associated queue of procs to run
44
+ def create
45
+ queue = Queue.new
46
+ thread = Thread.new do
47
+ while proc = queue.pop
48
+ begin
49
+ proc.call
50
+ rescue => ex
51
+ # Let this thread die on exceptions other than standard errors
52
+ end
53
+ put thread
54
+ end
55
+ end
56
+
57
+ thread[:queue] = queue
58
+ thread
59
+ end
60
+ end
61
+ end
62
+ end
63
+
@@ -1,3 +1,3 @@
1
1
  class Parallizer
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.4"
3
3
  end
data/lib/parallizer.rb CHANGED
@@ -1,10 +1,10 @@
1
- require 'work_queue'
2
1
  require 'parallizer/version'
3
2
  require 'parallizer/proxy'
4
3
  require 'parallizer/method_call_notifier'
4
+ require 'parallizer/thread_pool'
5
5
 
6
6
  class Parallizer
7
- WORK_QUEUE_SIZE = 10
7
+ WORK_QUEUE_SIZE = Parallizer::ThreadPool::THEAD_POOL_SIZE
8
8
 
9
9
  attr_reader :calls, :call_infos, :client, :proxy, :options
10
10
 
@@ -49,27 +49,10 @@ class Parallizer
49
49
  Parallizer::Proxy.new(client, call_infos)
50
50
  end
51
51
 
52
- def self.work_queue
53
- @parallizer_work_queue ||= create_work_queue
54
- end
55
-
56
- def self.create_work_queue
57
- work_queue = WorkQueue.new(WORK_QUEUE_SIZE)
58
-
59
- # Force threads to be available - the work_queue gem seems to not always create the threads
60
- WORK_QUEUE_SIZE.times do |i|
61
- work_queue.enqueue_b do
62
- 1000.times { |i| i ** 1000 }
63
- end
64
- end
65
-
66
- work_queue
67
- end
68
-
69
52
  private
70
53
 
71
54
  def enqueue_call_info(call_info, method_name_and_args)
72
- Parallizer.work_queue.enqueue_b do
55
+ Parallizer::ThreadPool.get do
73
56
  call_info[:mutex].synchronize do
74
57
  begin
75
58
  (call_info[:retries] + 1).times do
@@ -84,6 +67,7 @@ class Parallizer
84
67
  ensure
85
68
  call_info[:complete?] = true
86
69
  call_info[:condition_variable].broadcast
70
+ Parallizer::ThreadPool.put(Thread.current)
87
71
  end
88
72
  end
89
73
  end
data/parallizer.gemspec CHANGED
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
19
  s.require_paths = ["lib"]
20
20
 
21
- s.add_dependency 'work_queue', '~> 2.5.2'
21
+ s.add_development_dependency 'rake'
22
22
  s.add_development_dependency 'rspec', '~> 2.9.0'
23
23
  s.add_development_dependency 'always_execute', '~> 0.1.1'
24
24
  end
@@ -21,12 +21,6 @@ describe Parallizer do
21
21
  end
22
22
  end
23
23
 
24
- describe "#work_queue" do
25
- it "should have WORK_QUEUE_SIZE threads" do
26
- Parallizer.work_queue.cur_threads.should == Parallizer::WORK_QUEUE_SIZE
27
- end
28
- end
29
-
30
24
  describe "#add" do
31
25
  before do
32
26
  @client = TestObject.new
@@ -168,25 +162,49 @@ describe Parallizer do
168
162
  end
169
163
  end
170
164
 
171
- context "with multiple threads making calls to proxy before worker executed" do
172
- it "should not deadlock" do # note, this was deadlocking when using CV#signal instead of CV#broadcast
173
- # force our worker thread to run after two calls from other threads
174
- Parallizer::WORK_QUEUE_SIZE.times do
175
- Parallizer.work_queue.enqueue_b do
176
- sleep(2)
177
- end
178
- end
179
-
180
- # setup the proxy
181
- parallizer = Parallizer.new(TestObject.new)
182
- parallizer.add.another_method
165
+ context "with exceptions that are not standard errors" do
166
+ before do
167
+ @retries = 3
168
+ @client = stub('a client')
169
+ @method = :a_failing_method
170
+ (@retries + 1).times { @client.should_receive(@method).and_raise(Exception.new('an error')) }
171
+ end
172
+
173
+ execute do
174
+ parallizer = Parallizer.new(@client, :retries => @retries)
175
+ parallizer.add_call(@method)
183
176
  proxy = parallizer.create_proxy
184
-
185
- Thread.new do
186
- proxy.another_method # call in another thread must happen before call in main thread for it to deadlock
177
+ begin
178
+ proxy.send(@method)
179
+ rescue Exception
180
+ $!
187
181
  end
188
- sleep(1)
189
- proxy.another_method
182
+ end
183
+
184
+ it "should return successful method response" do
185
+ @execute_result.message.should == 'an error'
190
186
  end
191
187
  end
188
+
189
+ ## Unable to repro after switch to using ThreadPool instead of work_queue gem
190
+ # context "with multiple threads making calls to proxy before worker executed" do
191
+ # it "should not deadlock" do # note, this was deadlocking when using CV#signal instead of CV#broadcast
192
+ # Parallizer::WORK_QUEUE_SIZE.times do
193
+ # Parallizer::ThreadPool.get do
194
+ # sleep(2)
195
+ # end
196
+ # end
197
+ #
198
+ # # setup the proxy
199
+ # parallizer = Parallizer.new(TestObject.new)
200
+ # parallizer.add.another_method
201
+ # proxy = parallizer.create_proxy
202
+ #
203
+ # Thread.new do
204
+ # proxy.another_method # call in another thread must happen before call in main thread for it to deadlock
205
+ # end
206
+ # sleep(1)
207
+ # proxy.another_method
208
+ # end
209
+ # end
192
210
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parallizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.4
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-16 00:00:00.000000000 Z
12
+ date: 2012-10-22 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
- name: work_queue
15
+ name: rake
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ~>
19
+ - - ! '>='
20
20
  - !ruby/object:Gem::Version
21
- version: 2.5.2
22
- type: :runtime
21
+ version: '0'
22
+ type: :development
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ~>
27
+ - - ! '>='
28
28
  - !ruby/object:Gem::Version
29
- version: 2.5.2
29
+ version: '0'
30
30
  - !ruby/object:Gem::Dependency
31
31
  name: rspec
32
32
  requirement: !ruby/object:Gem::Requirement
@@ -75,6 +75,7 @@ files:
75
75
  - lib/parallizer.rb
76
76
  - lib/parallizer/method_call_notifier.rb
77
77
  - lib/parallizer/proxy.rb
78
+ - lib/parallizer/thread_pool.rb
78
79
  - lib/parallizer/version.rb
79
80
  - parallizer.gemspec
80
81
  - spec/parallizer/method_call_notifier_spec.rb
@@ -101,7 +102,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
101
102
  version: '0'
102
103
  requirements: []
103
104
  rubyforge_project: parallizer
104
- rubygems_version: 1.8.21
105
+ rubygems_version: 1.8.24
105
106
  signing_key:
106
107
  specification_version: 3
107
108
  summary: Execute your service layer in parallel