fizx-thread_pool 0.2.1 → 0.3.1
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/CHANGELOG +4 -0
- data/README +20 -0
- data/lib/thread_pool.rb +21 -8
- data/test/test_thread_pool.rb +25 -0
- metadata +1 -1
data/CHANGELOG
CHANGED
data/README
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
This code is still pretty early, and not yet used in production. That said, I am interested in feedback. You can send me a message on GitHub's internal messaging system (http://github.com/inbox/new/fizx).
|
|
2
|
+
|
|
1
3
|
A simple executor-style ThreadPool for Ruby (with tests, yay!)
|
|
2
4
|
|
|
3
5
|
Usage:
|
|
@@ -6,4 +8,22 @@ Usage:
|
|
|
6
8
|
require "thread_pool"
|
|
7
9
|
pool = ThreadPool.new(threads = 10)
|
|
8
10
|
pool.execute { puts "I'm writing from a thread" }
|
|
11
|
+
pool.join
|
|
12
|
+
|
|
13
|
+
It's often useful to make sure that the properties of Ruby's blocks don't bite you. The following code will usually print three nils, because n keeps changing.
|
|
14
|
+
|
|
15
|
+
pool = ThreadPool.new(threads = 10)
|
|
16
|
+
numbers = [1, 2, 3]
|
|
17
|
+
while n = numbers.shift
|
|
18
|
+
pool.execute { puts n.inspect }
|
|
19
|
+
end
|
|
20
|
+
pool.join
|
|
21
|
+
|
|
22
|
+
Passing arguments to execute avoids this. i.e.:
|
|
23
|
+
|
|
24
|
+
pool = ThreadPool.new(threads = 10)
|
|
25
|
+
numbers = [1, 2, 3]
|
|
26
|
+
while n = numbers.shift
|
|
27
|
+
pool.execute(n) {|local| puts local.inspect }
|
|
28
|
+
end
|
|
9
29
|
pool.join
|
data/lib/thread_pool.rb
CHANGED
|
@@ -1,17 +1,30 @@
|
|
|
1
1
|
# Hooray
|
|
2
2
|
require "thread"
|
|
3
|
+
require "rubygems"
|
|
4
|
+
require "loggable"
|
|
5
|
+
|
|
3
6
|
class ThreadPool
|
|
7
|
+
include Loggable
|
|
4
8
|
class Executor
|
|
9
|
+
include Loggable
|
|
5
10
|
attr_reader :active
|
|
6
11
|
|
|
7
12
|
def initialize(queue, mutex)
|
|
8
13
|
@thread = Thread.new do
|
|
9
14
|
loop do
|
|
10
|
-
mutex.synchronize { @
|
|
11
|
-
if @
|
|
15
|
+
mutex.synchronize { @tuple = queue.shift }
|
|
16
|
+
if @tuple
|
|
17
|
+
debug "Executor: processing #{@tuple.hash}"
|
|
18
|
+
args, block = @tuple
|
|
12
19
|
@active = true
|
|
13
|
-
|
|
14
|
-
|
|
20
|
+
begin
|
|
21
|
+
block.call(*args)
|
|
22
|
+
rescue Exception => e
|
|
23
|
+
error e.message
|
|
24
|
+
error e.backtrace.join("\n")
|
|
25
|
+
end
|
|
26
|
+
block.complete = true
|
|
27
|
+
debug "Executor: complete #{@tuple.hash}"
|
|
15
28
|
else
|
|
16
29
|
@active = false
|
|
17
30
|
sleep 0.01
|
|
@@ -38,7 +51,7 @@ class ThreadPool
|
|
|
38
51
|
end
|
|
39
52
|
|
|
40
53
|
# Runs the block at some time in the near future
|
|
41
|
-
def execute(&block)
|
|
54
|
+
def execute(*args, &block)
|
|
42
55
|
init_completable(block)
|
|
43
56
|
|
|
44
57
|
if @queue_limit > 0
|
|
@@ -46,13 +59,13 @@ class ThreadPool
|
|
|
46
59
|
end
|
|
47
60
|
|
|
48
61
|
@mutex.synchronize do
|
|
49
|
-
@queue << block
|
|
62
|
+
@queue << [args, block]
|
|
50
63
|
end
|
|
51
64
|
end
|
|
52
65
|
|
|
53
66
|
# Runs the block at some time in the near future, and blocks until complete
|
|
54
|
-
def synchronous_execute(&block)
|
|
55
|
-
execute(&block)
|
|
67
|
+
def synchronous_execute(*args, &block)
|
|
68
|
+
execute(*args, &block)
|
|
56
69
|
sleep 0.01 until block.complete?
|
|
57
70
|
end
|
|
58
71
|
|
data/test/test_thread_pool.rb
CHANGED
|
@@ -30,6 +30,31 @@ class TestThreadPool < Test::Unit::TestCase
|
|
|
30
30
|
assert_equal n - THREADS, @pool.waiting
|
|
31
31
|
end
|
|
32
32
|
|
|
33
|
+
class A
|
|
34
|
+
def initialize(i)
|
|
35
|
+
@i = i
|
|
36
|
+
end
|
|
37
|
+
attr_reader :i
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def test_context
|
|
41
|
+
@foo = []
|
|
42
|
+
@bar = (0...5).to_a
|
|
43
|
+
while c = @bar.shift
|
|
44
|
+
@pool.execute { @foo << c }
|
|
45
|
+
end
|
|
46
|
+
@pool.join
|
|
47
|
+
assert_equal [nil] * 5, @foo
|
|
48
|
+
|
|
49
|
+
@foo = []
|
|
50
|
+
@bar = (0...5).to_a
|
|
51
|
+
while c = @bar.shift
|
|
52
|
+
@pool.execute(c) {|n| @foo << n }
|
|
53
|
+
end
|
|
54
|
+
@pool.join
|
|
55
|
+
assert_equal (0...5).to_a, @foo
|
|
56
|
+
end
|
|
57
|
+
|
|
33
58
|
def test_queue_limit
|
|
34
59
|
n = 50
|
|
35
60
|
@foo = 0
|