thread 0.1.7 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3b410457cd8caaa3227527d9365650d3a02f8203
4
- data.tar.gz: 0430247c137897d69e59a88a6f57943cd58f46d5
3
+ metadata.gz: 6f1ac6a92f77e49dec38a35d8f17c607568f2702
4
+ data.tar.gz: 794e057cc2b9ea319f1051e13d7d69f7f61a92dd
5
5
  SHA512:
6
- metadata.gz: c55851e31ce9cc4897006df956bb3e5cff13418e9a294f0168cfdcf36e1deb4ccdf51b3559c53a513ad8d63d6836c23374c46db4ae26e3f061a1089db55a1754
7
- data.tar.gz: e91d1f1c0e483f2ed59bbe6966a1fd3604d2b8c082d6356e461d46233094c8d5c1415cf40b506ec22fd08027226af374d11a49621ebe0c74339021a5d7b857cc
6
+ metadata.gz: a8be737ccd11509f373d5a7c3d78a2e29fc1a0d6d414cac1a357ed4ee0472fa53f753de7f1cc4015cf453db34ddf42441f700c136566c8d17f65ce78a19ec810
7
+ data.tar.gz: 30461440ad2c050a41688c12e90bb7ce16df3bd706edb9f51d4bee4dd63dfa906f3e301da044f14be826f28a5ef740f9a2172495a17d6ab2122fb609d31fe2c5
@@ -5,6 +5,7 @@ rvm:
5
5
  - 1.9.3
6
6
  - 2.0.0
7
7
  - 2.1.0
8
+ - 2.2.1
8
9
  - ruby-head
9
10
  - jruby
10
- - rbx
11
+ - rbx
data/README.md CHANGED
@@ -174,7 +174,7 @@ require 'thread/pool'
174
174
  require 'thread/future'
175
175
 
176
176
  pool = Thread.pool 4
177
- f = pool {
177
+ f = pool.future {
178
178
  sleep 5
179
179
  42
180
180
  }
@@ -226,4 +226,4 @@ end
226
226
  3. Verify new and old specs are green (`rake`)
227
227
  4. Commit your changes (`git commit -am 'Add some feature'`)
228
228
  5. Push to the branch (`git push origin my-new-feature`)
229
- 6. Create a new Pull Request
229
+ 6. Create a new Pull Request
@@ -16,7 +16,7 @@ require 'thread'
16
16
  # messages are safe to be consumed.
17
17
  class Thread::Channel
18
18
  # Create a channel with optional initial messages and optional channel guard.
19
- def initialize (messages = [], &block)
19
+ def initialize(messages = [], &block)
20
20
  @messages = []
21
21
  @mutex = Mutex.new
22
22
  @check = block
@@ -30,7 +30,7 @@ class Thread::Channel
30
30
  #
31
31
  # If there's a guard, the value is passed to it, if the guard returns a falsy value
32
32
  # an ArgumentError exception is raised and the message is not sent.
33
- def send (what)
33
+ def send(what)
34
34
  if @check && !@check.call(what)
35
35
  raise ArgumentError, 'guard mismatch'
36
36
  end
@@ -47,7 +47,7 @@ class Thread::Channel
47
47
  # Receive a message, if there are none the call blocks until there's one.
48
48
  #
49
49
  # If a block is passed, it's used as guard to match to a message.
50
- def receive (&block)
50
+ def receive(&block)
51
51
  message = nil
52
52
  found = false
53
53
 
@@ -83,7 +83,7 @@ class Thread::Channel
83
83
  # Receive a message, if there are none the call returns nil.
84
84
  #
85
85
  # If a block is passed, it's used as guard to match to a message.
86
- def receive! (&block)
86
+ def receive!(&block)
87
87
  if block
88
88
  @messages.delete_at(@messages.find_index(&block))
89
89
  else
@@ -91,7 +91,7 @@ class Thread::Channel
91
91
  end
92
92
  end
93
93
 
94
- private
94
+ private
95
95
  def cond?
96
96
  instance_variable_defined? :@cond
97
97
  end
@@ -103,7 +103,7 @@ end
103
103
 
104
104
  class Thread
105
105
  # Helper to create a channel.
106
- def self.channel (*args, &block)
106
+ def self.channel(*args, &block)
107
107
  Thread::Channel.new(*args, &block)
108
108
  end
109
109
  end
@@ -18,7 +18,7 @@ class Thread::Every
18
18
  Restart = Class.new(Exception)
19
19
 
20
20
  # Create an every with the given seconds and block.
21
- def initialize (every, &block)
21
+ def initialize(every, &block)
22
22
  raise ArgumentError, 'no block given' unless block
23
23
 
24
24
  @every = every
@@ -67,14 +67,14 @@ class Thread::Every
67
67
  end
68
68
 
69
69
  # @private
70
- def self.finalizer (thread)
70
+ def self.finalizer(thread)
71
71
  proc {
72
72
  thread.raise Cancel.new
73
73
  }
74
74
  end
75
75
 
76
76
  # Change the number of seconds between each call.
77
- def every (seconds)
77
+ def every(seconds)
78
78
  @every = seconds
79
79
 
80
80
  restart
@@ -144,7 +144,7 @@ class Thread::Every
144
144
  end
145
145
 
146
146
  # Gets the current every value.
147
- def value (timeout = nil)
147
+ def value(timeout = nil)
148
148
  @mutex.synchronize {
149
149
  if @old
150
150
  cond.wait(@mutex, *timeout)
@@ -172,7 +172,7 @@ class Thread::Every
172
172
  }
173
173
  end
174
174
 
175
- private
175
+ private
176
176
  def cond?
177
177
  instance_variable_defined? :@cond
178
178
  end
@@ -184,14 +184,14 @@ end
184
184
 
185
185
  class Thread
186
186
  # Helper to create an every
187
- def self.every (every, &block)
187
+ def self.every(every, &block)
188
188
  Thread::Every.new(every, &block)
189
189
  end
190
190
  end
191
191
 
192
192
  module Kernel
193
193
  # Helper to create an every
194
- def every (every, &block)
194
+ def every(every, &block)
195
195
  Thread::Every.new(every, &block)
196
196
  end
197
197
  end
@@ -17,7 +17,7 @@ class Thread::Future
17
17
  Cancel = Class.new(Exception)
18
18
 
19
19
  # Create a future with the passed block and optionally using the passed pool.
20
- def initialize (pool = nil, &block)
20
+ def initialize(pool = nil, &block)
21
21
  raise ArgumentError, 'no block given' unless block
22
22
 
23
23
  @mutex = Mutex.new
@@ -38,7 +38,7 @@ class Thread::Future
38
38
  end
39
39
 
40
40
  # @private
41
- def self.finalizer (thread)
41
+ def self.finalizer(thread)
42
42
  proc {
43
43
  thread.raise Cancel.new
44
44
  }
@@ -92,7 +92,7 @@ class Thread::Future
92
92
  #
93
93
  # An optional timeout can be passed which will return nil if nothing has been
94
94
  # delivered.
95
- def value (timeout = nil)
95
+ def value(timeout = nil)
96
96
  raise @exception if exception?
97
97
 
98
98
  return @value if delivered?
@@ -111,7 +111,7 @@ class Thread::Future
111
111
  alias ~ value
112
112
 
113
113
  # Do the same as {#value}, but return nil in case of exception.
114
- def value! (timeout = nil)
114
+ def value!(timeout = nil)
115
115
  begin
116
116
  value(timeout)
117
117
  rescue Exception
@@ -121,7 +121,7 @@ class Thread::Future
121
121
 
122
122
  alias ! value!
123
123
 
124
- private
124
+ private
125
125
  def cond?
126
126
  instance_variable_defined? :@cond
127
127
  end
@@ -145,20 +145,20 @@ end
145
145
 
146
146
  class Thread
147
147
  # Helper to create a future
148
- def self.future (pool = nil, &block)
148
+ def self.future(pool = nil, &block)
149
149
  Thread::Future.new(pool, &block)
150
150
  end
151
151
  end
152
152
 
153
153
  module Kernel
154
154
  # Helper to create a future.
155
- def future (pool = nil, &block)
155
+ def future(pool = nil, &block)
156
156
  Thread::Future.new(pool, &block)
157
157
  end
158
158
  end
159
159
 
160
160
  class Thread::Pool
161
- def future (&block)
161
+ def future(&block)
162
162
  Thread.future self, &block
163
163
  end
164
164
  end
@@ -20,7 +20,7 @@ class Thread::Pipe
20
20
 
21
21
  # Create a Task which will call the passed function and get input
22
22
  # from the optional parameter and put output in the optional parameter.
23
- def initialize (func, input = Queue.new, output = Queue.new)
23
+ def initialize(func, input = Queue.new, output = Queue.new)
24
24
  @input = input
25
25
  @output = output
26
26
  @handling = false
@@ -54,7 +54,7 @@ class Thread::Pipe
54
54
  # output queue.
55
55
  #
56
56
  # The objects must respond to #enq and #deq, and block on #deq.
57
- def initialize (input = Queue.new, output = Queue.new)
57
+ def initialize(input = Queue.new, output = Queue.new)
58
58
  @tasks = []
59
59
 
60
60
  @input = input
@@ -64,7 +64,7 @@ class Thread::Pipe
64
64
  end
65
65
 
66
66
  # @private
67
- def self.finalizer (tasks)
67
+ def self.finalizer(tasks)
68
68
  proc {
69
69
  tasks.each(&:kill)
70
70
  }
@@ -72,7 +72,7 @@ class Thread::Pipe
72
72
 
73
73
  # Add a task to the pipe, it must respond to #call and #arity,
74
74
  # and #arity must return 1.
75
- def | (func)
75
+ def |(func)
76
76
  if func.arity != 1
77
77
  raise ArgumentError, 'wrong arity'
78
78
  end
@@ -91,7 +91,7 @@ class Thread::Pipe
91
91
  end
92
92
 
93
93
  # Insert data in the pipe.
94
- def enq (data)
94
+ def enq(data)
95
95
  return if @tasks.empty?
96
96
 
97
97
  @input.enq data
@@ -103,7 +103,7 @@ class Thread::Pipe
103
103
  alias << enq
104
104
 
105
105
  # Get an element from the output queue.
106
- def deq (non_block = false)
106
+ def deq(non_block = false)
107
107
  @output.deq(non_block)
108
108
  end
109
109
 
@@ -113,7 +113,7 @@ end
113
113
 
114
114
  class Thread
115
115
  # Helper to create a pipe.
116
- def self.| (func)
116
+ def self.|(func)
117
117
  Pipe.new | func
118
118
  end
119
119
  end
@@ -22,11 +22,11 @@ class Thread::Pool
22
22
  Timeout = Class.new(Exception)
23
23
  Asked = Class.new(Exception)
24
24
 
25
- attr_reader :pool, :timeout, :exception, :thread, :started_at
25
+ attr_reader :pool, :timeout, :exception, :thread, :started_at, :result
26
26
 
27
27
  # Create a task in the given pool which will pass the arguments to the
28
28
  # block.
29
- def initialize (pool, *args, &block)
29
+ def initialize(pool, *args, &block)
30
30
  @pool = pool
31
31
  @arguments = args
32
32
  @block = block
@@ -37,23 +37,34 @@ class Thread::Pool
37
37
  @terminated = false
38
38
  end
39
39
 
40
- def running?; @running; end
41
- def finished?; @finished; end
42
- def timeout?; @timedout; end
43
- def terminated?; @terminated; end
40
+ def running?
41
+ @running
42
+ end
43
+
44
+ def finished?
45
+ @finished
46
+ end
47
+
48
+ def timeout?
49
+ @timedout
50
+ end
51
+
52
+ def terminated?
53
+ @terminated
54
+ end
44
55
 
45
- # Execute the task in the given thread.
46
- def execute (thread)
56
+ # Execute the task.
57
+ def execute
47
58
  return if terminated? || running? || finished?
48
59
 
49
- @thread = thread
60
+ @thread = Thread.current
50
61
  @running = true
51
62
  @started_at = Time.now
52
63
 
53
64
  pool.__send__ :wake_up_timeout
54
65
 
55
66
  begin
56
- @block.call(*@arguments)
67
+ @result = @block.call(*@arguments)
57
68
  rescue Exception => reason
58
69
  if reason.is_a? Timeout
59
70
  @timedout = true
@@ -71,12 +82,12 @@ class Thread::Pool
71
82
  end
72
83
 
73
84
  # Raise an exception in the thread used by the task.
74
- def raise (exception)
85
+ def raise(exception)
75
86
  @thread.raise(exception)
76
87
  end
77
88
 
78
89
  # Terminate the exception with an optionally given exception.
79
- def terminate! (exception = Asked)
90
+ def terminate!(exception = Asked)
80
91
  return if terminated? || finished? || timeout?
81
92
 
82
93
  @terminated = true
@@ -92,10 +103,10 @@ class Thread::Pool
92
103
  end
93
104
 
94
105
  # Timeout the task after the given time.
95
- def timeout_after (time)
106
+ def timeout_after(time)
96
107
  @timeout = time
97
108
 
98
- pool.timeout_for self, time
109
+ pool.__send__ :timeout_for, self, time
99
110
 
100
111
  self
101
112
  end
@@ -110,7 +121,7 @@ class Thread::Pool
110
121
  #
111
122
  # A default block can be passed, which will be used to {#process} the passed
112
123
  # data.
113
- def initialize (min, max = nil, &block)
124
+ def initialize(min, max = nil, &block)
114
125
  @min = min
115
126
  @max = max || min
116
127
  @block = block
@@ -140,7 +151,9 @@ class Thread::Pool
140
151
  end
141
152
 
142
153
  # Check if the pool has been shut down.
143
- def shutdown?; !!@shutdown; end
154
+ def shutdown?
155
+ !!@shutdown
156
+ end
144
157
 
145
158
  # Check if auto trimming is enabled.
146
159
  def auto_trim?
@@ -151,11 +164,15 @@ class Thread::Pool
151
164
  # is reached.
152
165
  def auto_trim!
153
166
  @auto_trim = true
167
+
168
+ self
154
169
  end
155
170
 
156
171
  # Disable auto trimming.
157
172
  def no_auto_trim!
158
173
  @auto_trim = false
174
+
175
+ self
159
176
  end
160
177
 
161
178
  # Check if idle trimming is enabled.
@@ -167,15 +184,19 @@ class Thread::Pool
167
184
  # The minimum number of threads is respeced.
168
185
  def idle_trim!(timeout)
169
186
  @idle_trim = timeout
187
+
188
+ self
170
189
  end
171
190
 
172
191
  # Turn of idle trimming.
173
192
  def no_idle_trim!
174
193
  @idle_trim = nil
194
+
195
+ self
175
196
  end
176
197
 
177
198
  # Resize the pool with the passed arguments.
178
- def resize (min, max = nil)
199
+ def resize(min, max = nil)
179
200
  @min = min
180
201
  @max = max || min
181
202
 
@@ -200,9 +221,9 @@ class Thread::Pool
200
221
  def wait(what = :idle)
201
222
  case what
202
223
  when :done
203
- loop do
224
+ until done?
204
225
  @done_mutex.synchronize {
205
- return self if _done?
226
+ break if _done?
206
227
 
207
228
  @done.wait @done_mutex
208
229
  }
@@ -233,15 +254,7 @@ class Thread::Pool
233
254
  #
234
255
  # If no block is passed the default block will be used if present, an
235
256
  # ArgumentError will be raised otherwise.
236
- def process (*args, &block)
237
- unless block || @block
238
- raise ArgumentError, 'you must pass a block'
239
- end
240
-
241
- wait.process!(*args, &block)
242
- end
243
-
244
- def process! (*args, &block)
257
+ def process(*args, &block)
245
258
  unless block || @block
246
259
  raise ArgumentError, 'you must pass a block'
247
260
  end
@@ -263,11 +276,11 @@ class Thread::Pool
263
276
  task
264
277
  end
265
278
 
266
- alias << process!
279
+ alias << process
267
280
 
268
281
  # Trim the unused threads, if forced threads will be trimmed even if there
269
282
  # are tasks waiting.
270
- def trim (force = false)
283
+ def trim(force = false)
271
284
  @mutex.synchronize {
272
285
  if (force || @waiting > 0) && @spawned - @trim_requests > @min
273
286
  @trim_requests += 1
@@ -302,52 +315,28 @@ class Thread::Pool
302
315
  @cond.broadcast
303
316
  }
304
317
 
305
- join
306
-
307
- if @timeout
308
- @shutdown = :now
309
-
310
- wake_up_timeout
311
-
312
- @timeout.join
313
- end
314
-
315
- self
316
- end
317
-
318
- # Join on all threads in the pool.
319
- def join
320
318
  until @workers.empty?
321
319
  if worker = @workers.first
322
320
  worker.join
323
321
  end
324
322
  end
325
323
 
326
- self
327
- end
328
-
329
- # Define a timeout for a task.
330
- def timeout_for (task, timeout)
331
- unless @timeout
332
- spawn_timeout_thread
333
- end
334
-
335
- @mutex.synchronize {
336
- @timeouts[task] = timeout
324
+ if @timeout
325
+ @shutdown = :now
337
326
 
338
327
  wake_up_timeout
339
- }
328
+
329
+ @timeout.join
330
+ end
340
331
  end
341
332
 
342
333
  # Shutdown the pool after a given amount of time.
343
- def shutdown_after (timeout)
334
+ def shutdown_after(timeout)
344
335
  Thread.new {
345
336
  sleep timeout
346
337
 
347
338
  shutdown
348
339
  }
349
-
350
- self
351
340
  end
352
341
 
353
342
  class << self
@@ -358,6 +347,18 @@ class Thread::Pool
358
347
  end
359
348
 
360
349
  private
350
+ def timeout_for(task, timeout)
351
+ unless @timeout
352
+ spawn_timeout_thread
353
+ end
354
+
355
+ @mutex.synchronize {
356
+ @timeouts[task] = timeout
357
+
358
+ wake_up_timeout
359
+ }
360
+ end
361
+
361
362
  def wake_up_timeout
362
363
  if defined? @pipes
363
364
  @pipes.last.write_nonblock 'x' rescue nil
@@ -401,7 +402,7 @@ private
401
402
  @todo.shift
402
403
  } or break
403
404
 
404
- task.execute(thread)
405
+ task.execute
405
406
 
406
407
  break if @shutdown == :now
407
408
 
@@ -471,7 +472,7 @@ end
471
472
 
472
473
  class Thread
473
474
  # Helper to create a pool.
474
- def self.pool (*args, &block)
475
+ def self.pool(*args, &block)
475
476
  Thread::Pool.new(*args, &block)
476
477
  end
477
478
  end
@@ -17,20 +17,20 @@ class Thread::Process
17
17
  @@processes ||= {}
18
18
  end
19
19
 
20
- def self.register (name, process)
20
+ def self.register(name, process)
21
21
  all[name] = process
22
22
  end
23
23
 
24
- def self.unregister (name)
24
+ def self.unregister(name)
25
25
  all.delete(name)
26
26
  end
27
27
 
28
- def self.[] (name)
28
+ def self.[](name)
29
29
  all[name]
30
30
  end
31
31
 
32
32
  # Create a new process executing the block.
33
- def initialize (&block)
33
+ def initialize(&block)
34
34
  @channel = Thread::Channel.new
35
35
 
36
36
  Thread.new {
@@ -41,7 +41,7 @@ class Thread::Process
41
41
  end
42
42
 
43
43
  # Send a message to the process.
44
- def send (what)
44
+ def send(what)
45
45
  unless @channel
46
46
  raise RuntimeError, 'the process has terminated'
47
47
  end
@@ -53,7 +53,7 @@ class Thread::Process
53
53
 
54
54
  alias << send
55
55
 
56
- private
56
+ private
57
57
  def receive
58
58
  @channel.receive
59
59
  end
@@ -65,7 +65,7 @@ end
65
65
 
66
66
  class Thread
67
67
  # Helper to create a process.
68
- def self.process (&block)
68
+ def self.process(&block)
69
69
  Thread::Process.new(&block)
70
70
  end
71
71
  end
@@ -27,7 +27,7 @@ class Thread::Promise
27
27
  alias realized? delivered?
28
28
 
29
29
  # Deliver a value.
30
- def deliver (value)
30
+ def deliver(value)
31
31
  return self if delivered?
32
32
 
33
33
  @mutex.synchronize {
@@ -46,7 +46,7 @@ class Thread::Promise
46
46
  #
47
47
  # An optional timeout can be passed which will return nil if nothing has been
48
48
  # delivered.
49
- def value (timeout = nil)
49
+ def value(timeout = nil)
50
50
  return @value if delivered?
51
51
 
52
52
  @mutex.synchronize {
@@ -58,7 +58,7 @@ class Thread::Promise
58
58
 
59
59
  alias ~ value
60
60
 
61
- private
61
+ private
62
62
  def cond?
63
63
  instance_variable_defined? :@cond
64
64
  end
@@ -0,0 +1,78 @@
1
+ require 'thread/pool'
2
+
3
+ describe Thread::Pool do
4
+ it 'creates a new pool with the given amount of threads' do
5
+ pool = Thread.pool(4)
6
+
7
+ expect(pool.spawned).to eq(4)
8
+
9
+ pool.shutdown
10
+ end
11
+
12
+ it 'creates a new pool with the given amount of threads without spawning more than min' do
13
+ pool = Thread.pool(4, 8)
14
+
15
+ expect(pool.spawned).to eq(4)
16
+
17
+ pool.shutdown
18
+ end
19
+
20
+ it 'properly reports the backlog length' do
21
+ pool = Thread.pool(2)
22
+
23
+ pool.process { sleep 0.5 }
24
+ pool.process { sleep 0.5 }
25
+ pool.process { sleep 0.5 }
26
+
27
+ sleep 0.25
28
+
29
+ expect(pool.backlog).to eq(1)
30
+
31
+ pool.shutdown
32
+ end
33
+
34
+ it 'properly reports the pool is done' do
35
+ pool = Thread.pool(2)
36
+
37
+ pool.process { sleep 0.25 }
38
+ pool.process { sleep 0.25 }
39
+ pool.process { sleep 0.25 }
40
+
41
+ expect(pool.done?).to be(false)
42
+
43
+ sleep 0.75
44
+
45
+ expect(pool.done?).to be(true)
46
+
47
+ pool.shutdown
48
+ end
49
+
50
+ it 'properly reports the pool is idle' do
51
+ pool = Thread.pool(2)
52
+
53
+ pool.process { sleep 0.25 }
54
+ pool.process { sleep 0.5 }
55
+
56
+ expect(pool.idle?).to be(false)
57
+
58
+ sleep 0.30
59
+
60
+ expect(pool.idle?).to be(true)
61
+
62
+ pool.shutdown
63
+ end
64
+
65
+ it 'properly shutdowns the pool' do
66
+ result = []
67
+ pool = Thread.pool(4)
68
+
69
+ pool.process { sleep 0.1; result << 1 }
70
+ pool.process { sleep 0.2; result << 2 }
71
+ pool.process { sleep 0.3; result << 3 }
72
+ pool.process { sleep 0.4; result << 4 }
73
+
74
+ pool.shutdown
75
+
76
+ expect(result).to eq([1, 2, 3, 4])
77
+ end
78
+ end
@@ -4,7 +4,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
4
 
5
5
  Gem::Specification.new do |spec|
6
6
  spec.name = "thread"
7
- spec.version = "0.1.7"
7
+ spec.version = "0.2.0"
8
8
  spec.authors = ["meh."]
9
9
  spec.email = ["meh@schizofreni.co"]
10
10
  spec.summary = %q{Various extensions to the base thread library.}
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: thread
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.7
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - meh.
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-08 00:00:00.000000000 Z
11
+ date: 2015-04-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -67,6 +67,7 @@ files:
67
67
  - spec/thread/every_spec.rb
68
68
  - spec/thread/future_spec.rb
69
69
  - spec/thread/pipe_spec.rb
70
+ - spec/thread/pool_spec.rb
70
71
  - spec/thread/promise_spec.rb
71
72
  - thread.gemspec
72
73
  homepage: http://github.com/meh/ruby-thread
@@ -99,5 +100,6 @@ test_files:
99
100
  - spec/thread/every_spec.rb
100
101
  - spec/thread/future_spec.rb
101
102
  - spec/thread/pipe_spec.rb
103
+ - spec/thread/pool_spec.rb
102
104
  - spec/thread/promise_spec.rb
103
105
  has_rdoc: