parallizer 0.2.4 → 0.3.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/Gemfile.lock CHANGED
@@ -1,8 +1,8 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- parallizer (0.2.3)
5
- work_queue (~> 2.5.2)
4
+ parallizer (0.3.0)
5
+ work_queue
6
6
 
7
7
  GEM
8
8
  remote: http://rubygems.org/
@@ -9,31 +9,18 @@ class Parallizer
9
9
  end
10
10
 
11
11
  def method_missing(name, *args, &block)
12
- value = nil
13
-
14
12
  if call_info = @call_infos[[name, *args]]
15
- call_info[:mutex].synchronize do
16
- if !call_info[:complete?]
17
- # not done, so lets wait for signal of completion
18
- call_info[:condition_variable].wait(call_info[:mutex])
19
- end
20
- # we now have our result from the worker thread
21
-
22
- if call_info[:exception]
23
- # add the current call stack to the exception backtrace
24
- exception = call_info[:exception].clone
25
- exception.set_backtrace((call_info[:exception].backtrace || []) + caller)
26
- raise exception
27
- end
28
-
29
- value = call_info[:result]
13
+ if call_info[:exception]
14
+ # add the current call stack to the exception backtrace
15
+ exception = call_info[:exception].clone
16
+ exception.set_backtrace((call_info[:exception].backtrace || []) + caller)
17
+ raise exception
18
+ else
19
+ call_info[:result]
30
20
  end
31
21
  else
32
- # pass through to client since not added
33
- value = @client.send(*[name, *args], &block)
22
+ @client.send(*[name, *args], &block)
34
23
  end
35
-
36
- value
37
24
  end
38
25
 
39
26
  def respond_to?(name, include_private = false, &block)
@@ -1,3 +1,3 @@
1
1
  class Parallizer
2
- VERSION = "0.2.4"
2
+ VERSION = "0.3.0"
3
3
  end
data/lib/parallizer.rb CHANGED
@@ -1,10 +1,10 @@
1
+ require 'work_queue'
1
2
  require 'parallizer/version'
2
3
  require 'parallizer/proxy'
3
4
  require 'parallizer/method_call_notifier'
4
- require 'parallizer/thread_pool'
5
5
 
6
6
  class Parallizer
7
- WORK_QUEUE_SIZE = Parallizer::ThreadPool::THEAD_POOL_SIZE
7
+ WORK_QUEUE_SIZE = 10
8
8
 
9
9
  attr_reader :calls, :call_infos, :client, :proxy, :options
10
10
 
@@ -34,42 +34,43 @@ class Parallizer
34
34
  :complete? => false,
35
35
  :result => nil,
36
36
  :exception => nil,
37
- :condition_variable => ConditionVariable.new,
38
- :mutex => Mutex.new,
39
37
  :retries => options[:retries]
40
38
  }
41
39
  call_infos[method_name_and_args] = call_info
42
-
43
- enqueue_call_info(call_info, method_name_and_args)
44
40
  end
45
41
 
46
42
  def create_proxy
47
43
  raise ArgumentError, "Cannot create another proxy" if @proxy
48
44
 
45
+ execute
46
+
49
47
  Parallizer::Proxy.new(client, call_infos)
50
48
  end
51
49
 
52
50
  private
53
51
 
54
- def enqueue_call_info(call_info, method_name_and_args)
55
- Parallizer::ThreadPool.get do
56
- call_info[:mutex].synchronize do
57
- begin
58
- (call_info[:retries] + 1).times do
59
- begin
60
- call_info[:exception] = nil # reset exception before each send attempt
61
- call_info[:result] = client.send(*method_name_and_args)
62
- break # success
63
- rescue Exception => e
64
- call_info[:exception] = e
65
- end
52
+ def self.work_queue
53
+ # TODO: share the work queue among calling threads
54
+ Thread.current[:parallizer_work_queue] ||= WorkQueue.new(WORK_QUEUE_SIZE)
55
+ end
56
+
57
+ def execute
58
+ call_infos.each do |method_name_and_args, call_info|
59
+ Parallizer.work_queue.enqueue_b do
60
+ (call_info[:retries] + 1).times do
61
+ begin
62
+ call_info[:exception] = nil # reset exception before each send attempt
63
+ call_info[:result] = client.send(*method_name_and_args)
64
+ break # success
65
+ rescue Exception => e
66
+ call_info[:exception] = e
66
67
  end
67
- ensure
68
- call_info[:complete?] = true
69
- call_info[:condition_variable].broadcast
70
- Parallizer::ThreadPool.put(Thread.current)
71
68
  end
72
69
  end
73
70
  end
71
+
72
+ Parallizer.work_queue.join
73
+
74
+ Parallizer::Proxy.new(client, call_infos)
74
75
  end
75
76
  end
data/parallizer.gemspec CHANGED
@@ -18,6 +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'
21
22
  s.add_development_dependency 'rake'
22
23
  s.add_development_dependency 'rspec', '~> 2.9.0'
23
24
  s.add_development_dependency 'always_execute', '~> 0.1.1'
@@ -29,57 +29,39 @@ describe Parallizer::Proxy do
29
29
  @call_key += [:a_method, "some value"]
30
30
  end
31
31
 
32
- context "with not complete?" do
32
+ context "with an exception" do
33
33
  before do
34
- @call_info[:complete?] = false
35
- @call_info[:condition_variable].should_receive(:wait).with(@call_info[:mutex])
36
- @call_info[:result] = 'this is a value'
34
+ @call_info[:exception] = StandardError.new('An Exception')
35
+ @call_info[:exception].set_backtrace(["/tmp/foo.rb:123:in `in a_worker_thread_method'"])
37
36
  end
38
37
 
39
- it "should return the call_info result" do
40
- @execute_result.should == @call_info[:result]
38
+ execute do
39
+ def a_calling_thread_method
40
+ call_infos = { @call_key => @call_info }
41
+ proxy = Parallizer::Proxy.new(@client, call_infos)
42
+ proxy.send(*@call_key) rescue $!
43
+ end
44
+ a_calling_thread_method
45
+ end
46
+
47
+ it "should raise exception" do
48
+ @execute_result.class.should == @call_info[:exception].class
49
+ @execute_result.message.should == @call_info[:exception].message
50
+ end
51
+
52
+ it "should append backtrace of current call" do
53
+ @execute_result.backtrace.join.should match /a_worker_thread_method/
54
+ @execute_result.backtrace.join.should match /a_calling_thread_method/
41
55
  end
42
56
  end
43
57
 
44
- context "with complete? call info" do
58
+ context "with a result" do
45
59
  before do
46
- @call_info[:complete?] = true
47
- end
48
-
49
- context "with an exception" do
50
- before do
51
- @call_info[:exception] = StandardError.new('An Exception')
52
- @call_info[:exception].set_backtrace(["/tmp/foo.rb:123:in `in a_worker_thread_method'"])
53
- end
54
-
55
- execute do
56
- def a_calling_thread_method
57
- call_infos = { @call_key => @call_info }
58
- proxy = Parallizer::Proxy.new(@client, call_infos)
59
- proxy.send(*@call_key) rescue $!
60
- end
61
- a_calling_thread_method
62
- end
63
-
64
- it "should raise exception" do
65
- @execute_result.class.should == @call_info[:exception].class
66
- @execute_result.message.should == @call_info[:exception].message
67
- end
68
-
69
- it "should append backtrace of current call" do
70
- @execute_result.backtrace.join.should match /a_worker_thread_method/
71
- @execute_result.backtrace.join.should match /a_calling_thread_method/
72
- end
60
+ @call_info[:result] = "a result"
73
61
  end
74
62
 
75
- context "with a result" do
76
- before do
77
- @call_info[:result] = "a result"
78
- end
79
-
80
- it "should return result" do
81
- @execute_result.should == @call_info[:result]
82
- end
63
+ it "should return result" do
64
+ @execute_result.should == @call_info[:result]
83
65
  end
84
66
  end
85
67
  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.4
4
+ version: 0.3.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,8 +9,24 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-10-22 00:00:00.000000000 Z
12
+ date: 2012-10-30 00:00:00.000000000 Z
13
13
  dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: work_queue
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
14
30
  - !ruby/object:Gem::Dependency
15
31
  name: rake
16
32
  requirement: !ruby/object:Gem::Requirement
@@ -75,7 +91,6 @@ files:
75
91
  - lib/parallizer.rb
76
92
  - lib/parallizer/method_call_notifier.rb
77
93
  - lib/parallizer/proxy.rb
78
- - lib/parallizer/thread_pool.rb
79
94
  - lib/parallizer/version.rb
80
95
  - parallizer.gemspec
81
96
  - spec/parallizer/method_call_notifier_spec.rb
@@ -94,12 +109,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
94
109
  - - ! '>='
95
110
  - !ruby/object:Gem::Version
96
111
  version: '0'
112
+ segments:
113
+ - 0
114
+ hash: 4537061514701133663
97
115
  required_rubygems_version: !ruby/object:Gem::Requirement
98
116
  none: false
99
117
  requirements:
100
118
  - - ! '>='
101
119
  - !ruby/object:Gem::Version
102
120
  version: '0'
121
+ segments:
122
+ - 0
123
+ hash: 4537061514701133663
103
124
  requirements: []
104
125
  rubyforge_project: parallizer
105
126
  rubygems_version: 1.8.24
@@ -1,63 +0,0 @@
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
-