threadpool 0.0.1 → 0.0.1.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/README.md +15 -1
- data/lib/threadpool.rb +19 -16
- data/threadpool.gemspec +1 -1
- metadata +1 -1
data/README.md
CHANGED
@@ -4,8 +4,22 @@ All the implementations I looked at were either buggy or wasted CPU resources
|
|
4
4
|
for no apparent reason, for example used a sleep of 0.01 seconds to then check for
|
5
5
|
readiness and stuff like this.
|
6
6
|
|
7
|
-
This implementation uses `IO.select` instead, there is no timed sleep, it just
|
7
|
+
This implementation uses `IO.select` instead, there is no timed sleep, it just stays
|
8
8
|
there waiting for input, which will then come from a `#wake_up` call that writes on a pipe.
|
9
9
|
|
10
10
|
`IO.select` should be present everywhere so this should be cross-platform and doesn't waste
|
11
11
|
CPU resources. Keep in mind that each worker uses 2 file descriptors (reading and writing pipe).
|
12
|
+
|
13
|
+
Example
|
14
|
+
-------
|
15
|
+
|
16
|
+
```ruby
|
17
|
+
require 'threadpool'
|
18
|
+
|
19
|
+
pool = ThreadPool.new
|
20
|
+
pool.resize(4)
|
21
|
+
|
22
|
+
0.upto(10) { pool.process { sleep 2; puts 'lol' } }
|
23
|
+
```
|
24
|
+
|
25
|
+
You should get 4 lols every 2 seconds.
|
data/lib/threadpool.rb
CHANGED
@@ -36,19 +36,23 @@ class ThreadPool
|
|
36
36
|
class Worker
|
37
37
|
include Awakenable
|
38
38
|
|
39
|
-
def initialize (
|
40
|
-
@
|
41
|
-
@mutex
|
39
|
+
def initialize (pool)
|
40
|
+
@pool = pool
|
41
|
+
@mutex = Mutex.new
|
42
42
|
|
43
43
|
@thread = Thread.new {
|
44
44
|
loop do
|
45
45
|
if @block
|
46
|
-
|
46
|
+
begin
|
47
|
+
@block.call(*@args)
|
48
|
+
rescue Exception => e
|
49
|
+
@pool.raise(e)
|
50
|
+
end
|
47
51
|
|
48
52
|
@block = nil
|
49
53
|
@args = nil
|
50
54
|
|
51
|
-
@
|
55
|
+
@pool.wake_up
|
52
56
|
else
|
53
57
|
sleep
|
54
58
|
|
@@ -97,24 +101,27 @@ class ThreadPool
|
|
97
101
|
|
98
102
|
extend Forwardable
|
99
103
|
|
100
|
-
|
104
|
+
attr_reader :watcher, :size
|
105
|
+
def_delegators :@watcher, :sleep, :wake_up, :kill, :die?, :dead?, :join
|
106
|
+
def_delegators :@current, :raise
|
101
107
|
|
102
108
|
def initialize (size = 2)
|
103
109
|
@size = 0
|
104
110
|
@queue = Queue.new
|
105
111
|
@pool = []
|
106
|
-
@watcher = Worker.new
|
112
|
+
@watcher = Worker.new(self)
|
113
|
+
@current = Thread.current
|
107
114
|
|
108
115
|
@watcher.process {
|
109
116
|
loop do
|
110
|
-
|
111
|
-
next
|
117
|
+
sleep if @queue.empty?
|
118
|
+
next if @queue.empty?
|
112
119
|
|
113
120
|
begin
|
114
|
-
worker = @pool.find(&:available?) or
|
121
|
+
worker = @pool.find(&:available?) or sleep
|
115
122
|
end until worker
|
116
123
|
|
117
|
-
break if
|
124
|
+
break if die?
|
118
125
|
|
119
126
|
args, block = @queue.pop
|
120
127
|
|
@@ -127,16 +134,12 @@ class ThreadPool
|
|
127
134
|
resize(size)
|
128
135
|
end
|
129
136
|
|
130
|
-
def join
|
131
|
-
@watcher.join
|
132
|
-
end; alias wait join
|
133
|
-
|
134
137
|
def resize (size)
|
135
138
|
return if @size == size
|
136
139
|
|
137
140
|
if @size < size
|
138
141
|
1.upto(size - @size) {
|
139
|
-
@pool << Worker.new(
|
142
|
+
@pool << Worker.new(self)
|
140
143
|
}
|
141
144
|
else
|
142
145
|
1.upto(@size - size) {
|
data/threadpool.gemspec
CHANGED