mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
19e0d7c18e
iterations from 2000 to 250. When running on uniprocessor systems, every th.kill needs TIME_QUANTUM_USEC time (i.e. 100msec on posix systems). Because, "r.read 1" is 3 steps operations that 1) release GVL 2) read 3) acquire gvl and (1) invoke context switch to main thread. and then, main thread's th.kill resume (1), but not (2). Thus read interrupt need TIME_QUANTUM_USEC. Then maximum iteration is 30sec/100msec = 300. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@39688 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
111 lines
2.6 KiB
Ruby
111 lines
2.6 KiB
Ruby
require 'test/unit'
|
|
require 'thread'
|
|
require 'tmpdir'
|
|
require_relative '../ruby/envutil'
|
|
|
|
class TestQueue < Test::Unit::TestCase
|
|
def test_queue
|
|
grind(5, 1000, 15, Queue)
|
|
end
|
|
|
|
def test_sized_queue
|
|
grind(5, 1000, 15, SizedQueue, 1000)
|
|
end
|
|
|
|
def grind(num_threads, num_objects, num_iterations, klass, *args)
|
|
from_workers = klass.new(*args)
|
|
to_workers = klass.new(*args)
|
|
|
|
workers = (1..num_threads).map {
|
|
Thread.new {
|
|
while object = to_workers.pop
|
|
from_workers.push object
|
|
end
|
|
}
|
|
}
|
|
|
|
Thread.new {
|
|
num_iterations.times {
|
|
num_objects.times { to_workers.push 99 }
|
|
num_objects.times { from_workers.pop }
|
|
}
|
|
}.join
|
|
|
|
num_threads.times { to_workers.push nil }
|
|
workers.each { |t| t.join }
|
|
|
|
assert_equal 0, from_workers.size
|
|
assert_equal 0, to_workers.size
|
|
end
|
|
|
|
def test_sized_queue_initialize
|
|
q = SizedQueue.new(1)
|
|
assert_equal 1, q.max
|
|
assert_raise(ArgumentError) { SizedQueue.new(0) }
|
|
assert_raise(ArgumentError) { SizedQueue.new(-1) }
|
|
end
|
|
|
|
def test_sized_queue_assign_max
|
|
q = SizedQueue.new(2)
|
|
assert_equal(2, q.max)
|
|
q.max = 1
|
|
assert_equal(1, q.max)
|
|
assert_raise(ArgumentError) { q.max = 0 }
|
|
assert_equal(1, q.max)
|
|
assert_raise(ArgumentError) { q.max = -1 }
|
|
assert_equal(1, q.max)
|
|
end
|
|
|
|
def test_queue_pop_interrupt
|
|
q = Queue.new
|
|
t1 = Thread.new { q.pop }
|
|
sleep 0.01 until t1.stop?
|
|
t1.kill.join
|
|
assert_equal(0, q.num_waiting)
|
|
end
|
|
|
|
def test_sized_queue_pop_interrupt
|
|
q = SizedQueue.new(1)
|
|
t1 = Thread.new { q.pop }
|
|
sleep 0.01 until t1.stop?
|
|
t1.kill.join
|
|
assert_equal(0, q.num_waiting)
|
|
end
|
|
|
|
def test_sized_queue_push_interrupt
|
|
q = SizedQueue.new(1)
|
|
q.push(1)
|
|
t1 = Thread.new { q.push(2) }
|
|
sleep 0.01 until t1.stop?
|
|
t1.kill.join
|
|
assert_equal(0, q.num_waiting)
|
|
end
|
|
|
|
def test_thr_kill
|
|
bug5343 = '[ruby-core:39634]'
|
|
Dir.mktmpdir {|d|
|
|
timeout = 30
|
|
total_count = 250
|
|
begin
|
|
assert_normal_exit(<<-"_eom", bug5343, {:timeout => timeout, :chdir=>d})
|
|
require "thread"
|
|
#{total_count}.times do |i|
|
|
open("test_thr_kill_count", "w") {|f| f.puts i }
|
|
queue = Queue.new
|
|
r, w = IO.pipe
|
|
th = Thread.start {
|
|
queue.push(nil)
|
|
r.read 1
|
|
}
|
|
queue.pop
|
|
th.kill
|
|
th.join
|
|
end
|
|
_eom
|
|
rescue Timeout::Error
|
|
count = File.read("#{d}/test_thr_kill_count").to_i
|
|
flunk "only #{count}/#{total_count} done in #{timeout} seconds."
|
|
end
|
|
}
|
|
end
|
|
end
|