splib 1.2 → 1.3
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 +2 -0
- data/lib/splib.rb +1 -0
- data/lib/splib/Monitor.rb +86 -0
- data/splib.gemspec +1 -1
- data/tests/cases/Monitor.rb +132 -0
- metadata +11 -7
data/CHANGELOG
CHANGED
data/lib/splib.rb
CHANGED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
module Splib
|
4
|
+
|
5
|
+
class Monitor
|
6
|
+
def initialize
|
7
|
+
@threads = []
|
8
|
+
@locks = []
|
9
|
+
@lock_owner = nil
|
10
|
+
end
|
11
|
+
# timeout:: Wait for given amount of time
|
12
|
+
# Park a thread here
|
13
|
+
def wait(timeout=nil)
|
14
|
+
@threads << Thread.current
|
15
|
+
Thread.stop
|
16
|
+
true
|
17
|
+
end
|
18
|
+
# Park thread while block is true
|
19
|
+
def wait_while
|
20
|
+
while yield
|
21
|
+
wait
|
22
|
+
end
|
23
|
+
end
|
24
|
+
# Park thread until block is true
|
25
|
+
def wait_until
|
26
|
+
until yield
|
27
|
+
wait
|
28
|
+
end
|
29
|
+
end
|
30
|
+
# Wake up earliest thread
|
31
|
+
def signal
|
32
|
+
lock
|
33
|
+
t = @threads.shift
|
34
|
+
t.wakeup if t.alive?
|
35
|
+
unlock
|
36
|
+
end
|
37
|
+
# Wake up all threads
|
38
|
+
def broadcast
|
39
|
+
lock
|
40
|
+
@threads.each do |t|
|
41
|
+
t.wakeup if t.alive?
|
42
|
+
end
|
43
|
+
@threads.clear
|
44
|
+
unlock
|
45
|
+
end
|
46
|
+
# Number of threads waiting
|
47
|
+
def waiters
|
48
|
+
@threads.size
|
49
|
+
end
|
50
|
+
# Lock the monitor
|
51
|
+
def lock
|
52
|
+
stop = false
|
53
|
+
Thread.exclusive do
|
54
|
+
unless(@locks.empty?)
|
55
|
+
@locks << Thread.current
|
56
|
+
stop = true
|
57
|
+
else
|
58
|
+
@lock_owner = Thread.current
|
59
|
+
end
|
60
|
+
end
|
61
|
+
Thread.stop if stop
|
62
|
+
end
|
63
|
+
# Unlock the monitor
|
64
|
+
def unlock
|
65
|
+
unless(@lock_owner == Thread.current)
|
66
|
+
raise ThreadError.new("Not owner attepmting to unlock monitor")
|
67
|
+
else
|
68
|
+
Thread.exclusive do
|
69
|
+
unless(@locks.empty?)
|
70
|
+
@locks.delete{|t|!t.alive?}
|
71
|
+
@lock_owner = @locks.shift
|
72
|
+
@lock_owner.wakeup
|
73
|
+
else
|
74
|
+
@lock_owner = nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
# Lock the monitor, execute block and unlock the monitor
|
80
|
+
def synchronize
|
81
|
+
lock
|
82
|
+
yield
|
83
|
+
unlock
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
data/splib.gemspec
CHANGED
@@ -0,0 +1,132 @@
|
|
1
|
+
require 'splib'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class MonitorTest < Test::Unit::TestCase
|
5
|
+
def setup
|
6
|
+
Splib.load :Monitor
|
7
|
+
@monitor = Splib::Monitor.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def test_wait
|
11
|
+
t = []
|
12
|
+
5.times{ t << Thread.new{ @monitor.wait } }
|
13
|
+
sleep(0.01) # give threads a chance to wait
|
14
|
+
t.each do |thread|
|
15
|
+
assert(thread.alive?)
|
16
|
+
assert(thread.stop?)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_signal
|
21
|
+
output = []
|
22
|
+
t = []
|
23
|
+
5.times{ t << Thread.new{ @monitor.wait; output << 1 } }
|
24
|
+
sleep(0.01)
|
25
|
+
t.each do |thread|
|
26
|
+
assert(thread.alive?)
|
27
|
+
assert(thread.stop?)
|
28
|
+
end
|
29
|
+
assert(output.empty?)
|
30
|
+
@monitor.signal
|
31
|
+
sleep(0.01)
|
32
|
+
assert_equal(4, t.select{|th|th.alive?}.size)
|
33
|
+
assert_equal(1, output.size)
|
34
|
+
assert_equal(1, output.pop)
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_broadcast
|
38
|
+
output = []
|
39
|
+
t = []
|
40
|
+
5.times{ t << Thread.new{ @monitor.wait; output << 1 } }
|
41
|
+
sleep(0.01)
|
42
|
+
t.each do |thread|
|
43
|
+
assert(thread.alive?)
|
44
|
+
assert(thread.stop?)
|
45
|
+
end
|
46
|
+
assert(output.empty?)
|
47
|
+
@monitor.broadcast
|
48
|
+
sleep(0.01)
|
49
|
+
assert_equal(5, output.size)
|
50
|
+
5.times{ assert_equal(1, output.pop) }
|
51
|
+
assert_equal(5, t.select{|th|!th.alive?}.size)
|
52
|
+
end
|
53
|
+
|
54
|
+
def test_wait_while
|
55
|
+
stop = true
|
56
|
+
t = Thread.new{ @monitor.wait_while{ stop } }
|
57
|
+
sleep(0.01)
|
58
|
+
assert(t.alive?)
|
59
|
+
assert(t.stop?)
|
60
|
+
@monitor.signal
|
61
|
+
sleep(0.01)
|
62
|
+
assert(t.alive?)
|
63
|
+
assert(t.stop?)
|
64
|
+
@monitor.broadcast
|
65
|
+
sleep(0.01)
|
66
|
+
assert(t.alive?)
|
67
|
+
assert(t.stop?)
|
68
|
+
stop = false
|
69
|
+
@monitor.signal
|
70
|
+
sleep(0.01)
|
71
|
+
assert(!t.alive?)
|
72
|
+
assert(t.stop?)
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_wait_until
|
76
|
+
stop = false
|
77
|
+
t = Thread.new{ @monitor.wait_until{ stop } }
|
78
|
+
sleep(0.01)
|
79
|
+
assert(t.alive?)
|
80
|
+
assert(t.stop?)
|
81
|
+
@monitor.signal
|
82
|
+
sleep(0.01)
|
83
|
+
assert(t.alive?)
|
84
|
+
assert(t.stop?)
|
85
|
+
@monitor.broadcast
|
86
|
+
sleep(0.01)
|
87
|
+
assert(t.alive?)
|
88
|
+
assert(t.stop?)
|
89
|
+
stop = true
|
90
|
+
@monitor.signal
|
91
|
+
sleep(0.01)
|
92
|
+
assert(!t.alive?)
|
93
|
+
assert(t.stop?)
|
94
|
+
end
|
95
|
+
|
96
|
+
def test_waiters
|
97
|
+
t = []
|
98
|
+
(rand(20)+1).times{ t << Thread.new{ @monitor.wait } }
|
99
|
+
sleep(0.01)
|
100
|
+
assert_equal(t.size, @monitor.waiters)
|
101
|
+
@monitor.broadcast
|
102
|
+
sleep(0.01)
|
103
|
+
assert_equal(0, @monitor.waiters)
|
104
|
+
end
|
105
|
+
|
106
|
+
def test_lock_unlock
|
107
|
+
t = []
|
108
|
+
output = []
|
109
|
+
5.times{|i| t << Thread.new{ @monitor.lock; sleep((i+1)/100.0); output << i; @monitor.unlock;}}
|
110
|
+
sleep(0.011)
|
111
|
+
assert_equal(5, t.size)
|
112
|
+
assert_equal(0, output.pop)
|
113
|
+
sleep(0.011)
|
114
|
+
assert_equal(1, output.pop)
|
115
|
+
sleep(0.011)
|
116
|
+
assert_equal(2, output.pop)
|
117
|
+
sleep(0.011)
|
118
|
+
assert_equal(3, output.pop)
|
119
|
+
sleep(0.011)
|
120
|
+
assert_equal(4, output.pop)
|
121
|
+
end
|
122
|
+
|
123
|
+
def synchronize
|
124
|
+
t = []
|
125
|
+
output = []
|
126
|
+
5.times{|i| t << Thread.new{ @monitor.lock; sleep(i/100.0); output << i; @monitor.unlock;}}
|
127
|
+
@monitor.synchronize{ output << :done }
|
128
|
+
sleep(0.5)
|
129
|
+
assert_equal(6, output.size)
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: splib
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "1.
|
4
|
+
version: "1.3"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- spox
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2010-01-
|
12
|
+
date: 2010-01-12 00:00:00 -08:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -23,6 +23,8 @@ extra_rdoc_files:
|
|
23
23
|
- README.rdoc
|
24
24
|
- CHANGELOG
|
25
25
|
files:
|
26
|
+
- tests
|
27
|
+
- tests/cases
|
26
28
|
- tests/cases/Array.rb
|
27
29
|
- tests/cases/PriorityQueue.rb
|
28
30
|
- tests/cases/UrlShorteners.rb
|
@@ -30,11 +32,14 @@ files:
|
|
30
32
|
- tests/cases/Constants.rb
|
31
33
|
- tests/cases/CodeReloader.rb
|
32
34
|
- tests/cases/HumanIdealRandomIterator.rb
|
35
|
+
- tests/cases/Monitor.rb
|
33
36
|
- tests/cases/Conversions.rb
|
34
37
|
- tests/run_tests.rb
|
35
38
|
- tests/samplecode2.rb
|
36
39
|
- tests/samplecode1.rb
|
40
|
+
- lib
|
37
41
|
- lib/splib.rb
|
42
|
+
- lib/splib
|
38
43
|
- lib/splib/Array.rb
|
39
44
|
- lib/splib/PriorityQueue.rb
|
40
45
|
- lib/splib/UrlShorteners.rb
|
@@ -42,15 +47,14 @@ files:
|
|
42
47
|
- lib/splib/Constants.rb
|
43
48
|
- lib/splib/CodeReloader.rb
|
44
49
|
- lib/splib/HumanIdealRandomIterator.rb
|
50
|
+
- lib/splib/Monitor.rb
|
45
51
|
- lib/splib/Conversions.rb
|
46
52
|
- CHANGELOG
|
47
53
|
- LICENSE
|
48
54
|
- splib.gemspec
|
49
55
|
- README.rdoc
|
50
|
-
has_rdoc:
|
56
|
+
has_rdoc: false
|
51
57
|
homepage: http://github.com/spox/splib
|
52
|
-
licenses: []
|
53
|
-
|
54
58
|
post_install_message:
|
55
59
|
rdoc_options:
|
56
60
|
- --title
|
@@ -75,9 +79,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
75
79
|
requirements: []
|
76
80
|
|
77
81
|
rubyforge_project:
|
78
|
-
rubygems_version: 1.3.
|
82
|
+
rubygems_version: 1.3.1
|
79
83
|
signing_key:
|
80
|
-
specification_version:
|
84
|
+
specification_version: 2
|
81
85
|
summary: Spox Library
|
82
86
|
test_files: []
|
83
87
|
|