1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
| | root_dir = File.join(File.dirname(__FILE__), "../..")
require File.join(root_dir, "test/test_helper")
require File.join(root_dir, "lib/mongrel/semaphore")
class TestSemaphore < Test::Unit::TestCase
def setup
super
@semaphore = Semaphore.new
end
def test_wait_prevents_thread_from_running
thread = Thread.new { @semaphore.wait }
give_up_my_time_slice
assert thread.stop?
end
def test_signal_allows_waiting_thread_to_run
ran = false
thread = Thread.new { @semaphore.wait; ran = true }
give_up_my_time_slice
@semaphore.signal
give_up_my_time_slice
assert ran
end
def test_wait_allows_only_specified_number_of_resources
@semaphore = Semaphore.new(1)
run_count = 0
thread1 = Thread.new { @semaphore.wait; run_count += 1 }
thread2 = Thread.new { @semaphore.wait; run_count += 1 }
give_up_my_time_slice
assert_equal 1, run_count
end
def test_semaphore_serializes_threads
@semaphore = Semaphore.new(1)
result = ""
thread1 = Thread.new do
@semaphore.wait
4.times do |i|
give_up_my_time_slice
result << i.to_s
end
@semaphore.signal
end
thread2 = Thread.new do
@semaphore.wait
("a".."d").each do |char|
give_up_my_time_slice
result << char
end
@semaphore.signal
end
give_up_my_time_slice
@semaphore.wait
assert_equal "0123abcd", result
end
def test_synchronize_many_threads
@semaphore = Semaphore.new(1)
result = []
5.times do |i|
Thread.new do
@semaphore.wait
2.times { |j| result << [i, j] }
@semaphore.signal
end
end
give_up_my_time_slice
@semaphore.wait
5.times do |i|
2.times do |j|
assert_equal i, result[2 * i + j][0]
assert_equal j, result[2 * i + j][1]
end
end
end
def test_synchronize_ensures_signal
@semaphore = Semaphore.new(1)
threads = []
run_count = 0
threads << Thread.new do
@semaphore.synchronize { run_count += 1 }
end
threads << Thread.new do
@semaphore.synchronize { run_count += 1; raise "I'm throwing an error." }
end
threads << Thread.new do
@semaphore.synchronize { run_count += 1 }
end
give_up_my_time_slice
@semaphore.wait
assert !threads.any? { |thread| thread.alive? }
assert_equal 3, run_count
end
private
def give_up_my_time_slice
sleep(1)
end
end
|