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 CHANGED
@@ -1,3 +1,7 @@
1
+ 0.3.1
2
+ - rescue Thread errors, use Loggable to print backtraces
3
+ 0.3.0
4
+ - allow execute to take args, so we can reset the scope
1
5
  0.2.1
2
6
  - mutex in case Array#<< and Array#shift aren't atomic
3
7
  0.2.0
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
@@ -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 { @block = queue.shift }
11
- if @block
15
+ mutex.synchronize { @tuple = queue.shift }
16
+ if @tuple
17
+ debug "Executor: processing #{@tuple.hash}"
18
+ args, block = @tuple
12
19
  @active = true
13
- @block.call
14
- @block.complete = true
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
 
@@ -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
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fizx-thread_pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyle Maxwell