concur 0.0.2 → 0.0.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/README.markdown +1 -1
- data/lib/executor.rb +40 -16
- data/lib/future.rb +17 -14
- data/lib/thread_pool.rb +2 -3
- data/test/executor_spec.rb +7 -7
- data/test/job.rb +1 -1
- metadata +7 -6
data/README.markdown
CHANGED
@@ -1 +1 @@
|
|
1
|
-
# Concur - A concurrency library for Ruby
|
1
|
+
# Concur - A concurrency library for Ruby inspired by java.util.concurrency
|
data/lib/executor.rb
CHANGED
@@ -19,31 +19,55 @@ module Concur
|
|
19
19
|
|
20
20
|
end
|
21
21
|
|
22
|
-
def self.
|
22
|
+
def self.new_single_threaded_executor(options={})
|
23
23
|
executor = Executor.new
|
24
|
-
executor.thread_pool =
|
25
|
-
p executor.thread_pool
|
24
|
+
executor.thread_pool = SingleThreaded.new
|
26
25
|
executor
|
27
26
|
end
|
28
27
|
|
29
|
-
def
|
30
|
-
|
28
|
+
def self.new_multi_threaded_executor(options={})
|
29
|
+
executor = Executor.new
|
30
|
+
executor.thread_pool = MultiThreaded.new
|
31
|
+
executor
|
32
|
+
end
|
33
|
+
|
34
|
+
def self.new_thread_pool_executor(max_size, options={})
|
35
|
+
executor = Executor.new
|
36
|
+
executor.thread_pool = ThreadPool.new(max_size)
|
37
|
+
executor
|
38
|
+
end
|
39
|
+
|
40
|
+
def execute(runnable=nil, &blk)
|
31
41
|
f = Future.new(runnable, &blk)
|
32
|
-
|
33
|
-
@thread_pool.process(f)
|
34
|
-
else
|
35
|
-
@thread = Thread.new do
|
36
|
-
f.thread = @thread
|
37
|
-
f.call
|
38
|
-
end
|
39
|
-
end
|
42
|
+
@thread_pool.process(f)
|
40
43
|
f
|
41
44
|
end
|
42
45
|
|
43
46
|
def shutdown
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
+
@thread_pool.shutdown
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# todo: should maybe have these backends extend Executor and just override what's necessary
|
52
|
+
class SingleThreaded
|
53
|
+
def process(f)
|
54
|
+
f.call
|
55
|
+
end
|
56
|
+
|
57
|
+
def shutdown
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class MultiThreaded
|
62
|
+
def process(f)
|
63
|
+
@thread = Thread.new do
|
64
|
+
f.thread = @thread
|
65
|
+
f.call
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def shutdown
|
70
|
+
|
47
71
|
end
|
48
72
|
end
|
49
73
|
end
|
data/lib/future.rb
CHANGED
@@ -3,20 +3,10 @@ module Concur
|
|
3
3
|
#An Future is a class that captures the results of a threaded object so you can retreive the results later.
|
4
4
|
#This is what is returned from Executors.
|
5
5
|
class Future
|
6
|
-
attr_accessor :thread
|
6
|
+
attr_accessor :thread
|
7
7
|
|
8
8
|
def initialize(runnable=nil, &block)
|
9
9
|
|
10
|
-
# if block
|
11
|
-
# @thread = Thread.new do
|
12
|
-
# @result = yield
|
13
|
-
# end
|
14
|
-
# else
|
15
|
-
# @thread = Thread.new do
|
16
|
-
# @result = runnable.run
|
17
|
-
# end
|
18
|
-
# end
|
19
|
-
|
20
10
|
@mutex = Mutex.new
|
21
11
|
@cv = ConditionVariable.new
|
22
12
|
@callable = runnable
|
@@ -27,15 +17,25 @@ module Concur
|
|
27
17
|
end
|
28
18
|
|
29
19
|
def run
|
30
|
-
|
31
|
-
|
32
|
-
|
20
|
+
begin
|
21
|
+
@result = @callable.call
|
22
|
+
rescue Exception => ex
|
23
|
+
@ex = ex
|
24
|
+
end
|
25
|
+
@mutex.synchronize do # do we even need to synchronize? run should only ever be called once
|
26
|
+
@complete = true
|
27
|
+
@cv.broadcast
|
28
|
+
end
|
33
29
|
end
|
34
30
|
|
35
31
|
def call
|
36
32
|
run
|
37
33
|
end
|
38
34
|
|
35
|
+
def complete?
|
36
|
+
@complete
|
37
|
+
end
|
38
|
+
|
39
39
|
# Returns results. Will wait for thread to complete execution if not already complete.
|
40
40
|
def get
|
41
41
|
# @thread.value
|
@@ -44,6 +44,9 @@ module Concur
|
|
44
44
|
@cv.wait(@mutex)
|
45
45
|
end
|
46
46
|
end
|
47
|
+
if @ex
|
48
|
+
raise @ex
|
49
|
+
end
|
47
50
|
@result
|
48
51
|
end
|
49
52
|
end
|
data/lib/thread_pool.rb
CHANGED
@@ -37,12 +37,11 @@ module Concur
|
|
37
37
|
while @running
|
38
38
|
f = @queue.pop
|
39
39
|
f.thread = t
|
40
|
-
f.pool = self
|
41
40
|
f.call
|
42
41
|
end
|
43
|
-
Concur.logger.info "Thread dying " + t.inspect
|
42
|
+
# Concur.logger.info "Thread dying " + t.inspect
|
44
43
|
end
|
45
|
-
Concur.logger.
|
44
|
+
Concur.logger.debug "Created new thread " + t.inspect
|
46
45
|
@threads << t
|
47
46
|
end
|
48
47
|
end
|
data/test/executor_spec.rb
CHANGED
@@ -6,11 +6,12 @@ require_relative 'job'
|
|
6
6
|
describe Concur::Executor do
|
7
7
|
describe "#score" do
|
8
8
|
it "runs faster in parallel" do
|
9
|
+
times = 10
|
9
10
|
|
10
11
|
job = Job.new(1)
|
11
12
|
puts 'runnable? ' + job.is_a?(Concur::Runnable).to_s
|
12
13
|
start_time = Time.now
|
13
|
-
|
14
|
+
times.times do |i|
|
14
15
|
job = Job.new(i)
|
15
16
|
job.run
|
16
17
|
end
|
@@ -20,14 +21,13 @@ describe Concur::Executor do
|
|
20
21
|
puts '---------------'
|
21
22
|
|
22
23
|
puts "Now for concurrent"
|
23
|
-
executor = Concur::Executor.
|
24
|
+
executor = Concur::Executor.new_multi_threaded_executor
|
24
25
|
start_time = Time.now
|
25
26
|
|
26
27
|
jobs = []
|
27
|
-
|
28
|
+
times.times do |i|
|
28
29
|
job = Job.new(i)
|
29
|
-
|
30
|
-
jobs << future
|
30
|
+
jobs << executor.execute(job)
|
31
31
|
end
|
32
32
|
jobs.each do |j|
|
33
33
|
puts "uber fast result=#{j.get}"
|
@@ -38,11 +38,11 @@ describe Concur::Executor do
|
|
38
38
|
concurrent_duration.should be < (non_concurrent_duration/2)
|
39
39
|
|
40
40
|
puts "Now for pooled"
|
41
|
-
executor = Concur::Executor.new_thread_pool_executor(
|
41
|
+
executor = Concur::Executor.new_thread_pool_executor(10)
|
42
42
|
start_time = Time.now
|
43
43
|
|
44
44
|
jobs = []
|
45
|
-
|
45
|
+
times.times do |i|
|
46
46
|
job = Job.new(i)
|
47
47
|
future = executor.execute(job)
|
48
48
|
jobs << future
|
data/test/job.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: concur
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ default_executable:
|
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec
|
17
|
-
requirement: &
|
17
|
+
requirement: &25999668 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,8 +22,9 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
26
|
-
description: A concurrency library for Ruby
|
25
|
+
version_requirements: *25999668
|
26
|
+
description: A concurrency library for Ruby inspired by java.util.concurrency. By
|
27
|
+
http://www.appoxy.com
|
27
28
|
email: travis@appoxy.com
|
28
29
|
executables: []
|
29
30
|
extensions: []
|
@@ -59,10 +60,10 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
59
60
|
version: '0'
|
60
61
|
requirements: []
|
61
62
|
rubyforge_project:
|
62
|
-
rubygems_version: 1.6.
|
63
|
+
rubygems_version: 1.6.2
|
63
64
|
signing_key:
|
64
65
|
specification_version: 3
|
65
|
-
summary: A concurrency library for Ruby
|
66
|
+
summary: A concurrency library for Ruby inspired by java.util.concurrency. By http://www.appoxy.com
|
66
67
|
test_files:
|
67
68
|
- test/executor_spec.rb
|
68
69
|
- test/job.rb
|