ghazel-SystemTimer 1.2.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/COPYING +340 -0
- data/ChangeLog +51 -0
- data/LICENSE +58 -0
- data/README +196 -0
- data/ext/system_timer/extconf.rb +3 -0
- data/ext/system_timer/system_timer_native.c +325 -0
- data/lib/system_timer.rb +115 -0
- data/lib/system_timer/concurrent_timer_pool.rb +89 -0
- data/lib/system_timer/thread_timer.rb +22 -0
- data/lib/system_timer_stub.rb +20 -0
- data/test/all_tests.rb +3 -0
- data/test/system_timer/concurrent_timer_pool_unit_test.rb +291 -0
- data/test/system_timer/thread_timer_test.rb +20 -0
- data/test/system_timer_functional_test.rb +282 -0
- data/test/system_timer_unit_test.rb +110 -0
- data/test/test_helper.rb +10 -0
- metadata +75 -0
@@ -0,0 +1,20 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../test_helper'
|
2
|
+
|
3
|
+
unit_tests do
|
4
|
+
|
5
|
+
test "trigger_time returns the time given in the constructor" do
|
6
|
+
timer = SystemTimer::ThreadTimer.new(:a_tigger_time, nil)
|
7
|
+
assert_equal :a_tigger_time, timer.trigger_time
|
8
|
+
end
|
9
|
+
|
10
|
+
test "thread returns the thread given in the constructor" do
|
11
|
+
timer = SystemTimer::ThreadTimer.new(nil, :a_thread)
|
12
|
+
assert_equal :a_thread, timer.thread
|
13
|
+
end
|
14
|
+
|
15
|
+
test "to_s retruns a human friendly description of the timer" do
|
16
|
+
assert_match /<ThreadTimer :time => 24, :thread => #<Thread(.*)>, :exception_class => Timeout::Error>/,
|
17
|
+
SystemTimer::ThreadTimer.new(24, Thread.current).to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,282 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
functional_tests do
|
4
|
+
|
5
|
+
DEFAULT_ERROR_MARGIN = 2
|
6
|
+
|
7
|
+
test "original_ruby_sigalrm_handler is nil after reset" do
|
8
|
+
SystemTimer.send(:install_ruby_sigalrm_handler)
|
9
|
+
SystemTimer.send(:reset_original_ruby_sigalrm_handler)
|
10
|
+
assert_nil SystemTimer.send(:original_ruby_sigalrm_handler)
|
11
|
+
end
|
12
|
+
|
13
|
+
test "original_ruby_sigalrm_handler is set to existing handler after " +
|
14
|
+
"install_ruby_sigalrm_handler when save_previous_handler is true" do
|
15
|
+
SystemTimer.expects(:trap).with('SIGALRM').returns(:an_existing_handler)
|
16
|
+
SystemTimer.send(:install_ruby_sigalrm_handler)
|
17
|
+
assert_equal :an_existing_handler, SystemTimer.send(:original_ruby_sigalrm_handler)
|
18
|
+
end
|
19
|
+
|
20
|
+
test "restore_original_ruby_sigalrm_handler traps sigalrm using original_ruby_sigalrm_handler" do
|
21
|
+
SystemTimer.stubs(:original_ruby_sigalrm_handler).returns(:the_original_handler)
|
22
|
+
SystemTimer.expects(:trap).with('SIGALRM', :the_original_handler)
|
23
|
+
SystemTimer.send :restore_original_ruby_sigalrm_handler
|
24
|
+
end
|
25
|
+
|
26
|
+
test "restore_original_ruby_sigalrm_handler resets original_ruby_sigalrm_handler" do
|
27
|
+
SystemTimer.stubs(:trap)
|
28
|
+
SystemTimer.expects(:reset_original_ruby_sigalrm_handler)
|
29
|
+
SystemTimer.send :restore_original_ruby_sigalrm_handler
|
30
|
+
end
|
31
|
+
|
32
|
+
test "restore_original_ruby_sigalrm_handler reset SIGALRM handler to default when original_ruby_sigalrm_handler is nil" do
|
33
|
+
SystemTimer.stubs(:original_ruby_sigalrm_handler)
|
34
|
+
SystemTimer.expects(:trap).with('SIGALRM', 'DEFAULT')
|
35
|
+
SystemTimer.stubs(:reset_original_ruby_sigalrm_handler)
|
36
|
+
SystemTimer.send :restore_original_ruby_sigalrm_handler
|
37
|
+
end
|
38
|
+
|
39
|
+
test "restore_original_ruby_sigalrm_handler resets original_ruby_sigalrm_handler when trap raises" do
|
40
|
+
SystemTimer.stubs(:trap).returns(:the_original_handler)
|
41
|
+
SystemTimer.send(:install_ruby_sigalrm_handler)
|
42
|
+
SystemTimer.expects(:trap).raises("next time maybe...")
|
43
|
+
SystemTimer.expects(:reset_original_ruby_sigalrm_handler)
|
44
|
+
|
45
|
+
SystemTimer.send(:restore_original_ruby_sigalrm_handler) rescue nil
|
46
|
+
end
|
47
|
+
|
48
|
+
test "timeout_after raises TimeoutError if block takes too long" do
|
49
|
+
assert_raises(Timeout::Error) do
|
50
|
+
SystemTimer.timeout_after(1) {sleep 5}
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
test "timeout_after timeout can be a fraction of a second" do
|
55
|
+
assert_raises(Timeout::Error) do
|
56
|
+
SystemTimer.timeout_after(0.2) {sleep 3}
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
test "timeout_after raises a custom timeout when block takes too long and a custom exception class is provided" do
|
62
|
+
ACustomException = Class.new(Exception)
|
63
|
+
assert_raises(ACustomException) do
|
64
|
+
SystemTimer.timeout_after(1, ACustomException) {sleep 5}
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
test "timeout_after does not raises Timeout Error if block completes in time" do
|
69
|
+
SystemTimer.timeout_after(5) {sleep 1}
|
70
|
+
end
|
71
|
+
|
72
|
+
test "timeout_after returns the value returned by the black" do
|
73
|
+
assert_equal :block_value, SystemTimer.timeout_after(1) {:block_value}
|
74
|
+
end
|
75
|
+
|
76
|
+
test "timeout_after raises TimeoutError in thread that called timeout_after" do
|
77
|
+
raised_thread = nil
|
78
|
+
other_thread = Thread.new do
|
79
|
+
begin
|
80
|
+
SystemTimer.timeout_after(1) {sleep 5}
|
81
|
+
flunk "Should have timed out"
|
82
|
+
rescue Timeout::Error
|
83
|
+
raised_thread = Thread.current
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
other_thread.join
|
88
|
+
assert_equal other_thread, raised_thread
|
89
|
+
end
|
90
|
+
|
91
|
+
test "cancelling a timer that was installed restores previous ruby handler for SIG_ALRM" do
|
92
|
+
begin
|
93
|
+
fake_original_ruby_handler = proc {}
|
94
|
+
initial_ruby_handler = trap "SIGALRM", fake_original_ruby_handler
|
95
|
+
SystemTimer.install_first_timer_and_save_original_configuration 3
|
96
|
+
SystemTimer.restore_original_configuration
|
97
|
+
assert_equal fake_original_ruby_handler, trap("SIGALRM", "IGNORE")
|
98
|
+
ensure # avoid interfering with test infrastructure
|
99
|
+
trap("SIGALRM", initial_ruby_handler) if initial_ruby_handler
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
test "debug_enabled returns true after enabling debug" do
|
104
|
+
begin
|
105
|
+
SystemTimer.disable_debug
|
106
|
+
SystemTimer.enable_debug
|
107
|
+
assert_equal true, SystemTimer.debug_enabled?
|
108
|
+
ensure
|
109
|
+
SystemTimer.disable_debug
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
test "debug_enabled returns false after disable debug" do
|
114
|
+
begin
|
115
|
+
SystemTimer.enable_debug
|
116
|
+
SystemTimer.disable_debug
|
117
|
+
assert_equal false, SystemTimer.debug_enabled?
|
118
|
+
ensure
|
119
|
+
SystemTimer.disable_debug
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
test "timeout offers an API fully compatible with timeout.rb" do
|
124
|
+
assert_raises(Timeout::Error) do
|
125
|
+
SystemTimer.timeout(1) {sleep 5}
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# Disable this test as it is failing on Ubuntu. The problem is that
|
130
|
+
# for some reason M.R.I 1.8 is trapping the Ruby signals at the
|
131
|
+
# time the system SIGALRM is delivered, hence we do not timeout as
|
132
|
+
# quickly as we should. Needs further investigation. At least the
|
133
|
+
# SIGALRM ensures that the system will schedule M.R.I. native thread.
|
134
|
+
#
|
135
|
+
#
|
136
|
+
# test "while exact timeouts cannot be guaranted the timeout should not exceed the provided timeout by 2 seconds" do
|
137
|
+
# start = Time.now
|
138
|
+
# begin
|
139
|
+
# SystemTimer.timeout_after(2) do
|
140
|
+
# open "http://www.invalid.domain.comz"
|
141
|
+
# end
|
142
|
+
# raise "should never get there"
|
143
|
+
# rescue SocketError => e
|
144
|
+
# rescue Timeout::Error => e
|
145
|
+
# end
|
146
|
+
# elapsed = Time.now - start
|
147
|
+
# assert elapsed < 4, "Got #{elapsed} s, expected 2, at most 4"
|
148
|
+
# end
|
149
|
+
|
150
|
+
|
151
|
+
test "timeout are enforced on system calls" do
|
152
|
+
assert_timeout_within(3) do
|
153
|
+
SystemTimer.timeout(3) do
|
154
|
+
sleep 30
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
|
159
|
+
test "timeout work when spawning a different thread" do
|
160
|
+
assert_timeout_within(3) do
|
161
|
+
thread = Thread.new do
|
162
|
+
SystemTimer.timeout(3) do
|
163
|
+
sleep 60
|
164
|
+
end
|
165
|
+
end
|
166
|
+
thread.join
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
test "can set multiple serial timers" do
|
171
|
+
10.times do |i|
|
172
|
+
print(i) & STDOUT.flush
|
173
|
+
assert_timeout_within(1) do
|
174
|
+
SystemTimer.timeout(1) do
|
175
|
+
sleep 60
|
176
|
+
end
|
177
|
+
end
|
178
|
+
end
|
179
|
+
end
|
180
|
+
|
181
|
+
test "can set multiple serial timers with fractional timeout" do
|
182
|
+
10.times do |i|
|
183
|
+
print(i) & STDOUT.flush
|
184
|
+
assert_timeout_within(0.5) do
|
185
|
+
SystemTimer.timeout(0.5) do
|
186
|
+
sleep 60
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
test "timeout work when setting concurrent timers, the first one expiring before the second one" do
|
193
|
+
first_thread = Thread.new do
|
194
|
+
assert_timeout_within(3) do
|
195
|
+
SystemTimer.timeout(3) do
|
196
|
+
sleep 60
|
197
|
+
end
|
198
|
+
end
|
199
|
+
end
|
200
|
+
second_thread = Thread.new do
|
201
|
+
assert_timeout_within(5) do
|
202
|
+
SystemTimer.timeout(5) do
|
203
|
+
sleep 60
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
first_thread.join
|
208
|
+
second_thread.join
|
209
|
+
end
|
210
|
+
|
211
|
+
test "timeout work when setting concurrent timers, the second one expiring before the first one" do
|
212
|
+
|
213
|
+
first_thread = Thread.new do
|
214
|
+
assert_timeout_within(10) do
|
215
|
+
SystemTimer.timeout(10) do
|
216
|
+
sleep 60
|
217
|
+
end
|
218
|
+
end
|
219
|
+
end
|
220
|
+
second_thread = Thread.new do
|
221
|
+
assert_timeout_within(3) do
|
222
|
+
SystemTimer.timeout(3) do
|
223
|
+
sleep 60
|
224
|
+
end
|
225
|
+
end
|
226
|
+
end
|
227
|
+
first_thread.join
|
228
|
+
second_thread.join
|
229
|
+
end
|
230
|
+
|
231
|
+
test "timeout work when setting concurrent timers with the exact same timeout" do
|
232
|
+
|
233
|
+
first_thread = Thread.new do
|
234
|
+
assert_timeout_within(2) do
|
235
|
+
SystemTimer.timeout(2) do
|
236
|
+
sleep 60
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|
240
|
+
second_thread = Thread.new do
|
241
|
+
assert_timeout_within(2) do
|
242
|
+
SystemTimer.timeout(2) do
|
243
|
+
sleep 60
|
244
|
+
end
|
245
|
+
end
|
246
|
+
end
|
247
|
+
first_thread.join
|
248
|
+
second_thread.join
|
249
|
+
end
|
250
|
+
|
251
|
+
test "timeout works with random concurrent timers dynamics" do
|
252
|
+
all_threads = []
|
253
|
+
|
254
|
+
10.times do
|
255
|
+
a_timeout = [1, (rand(10)).to_f].max
|
256
|
+
all_threads << Thread.new do
|
257
|
+
assert_timeout_within(a_timeout, 10) do
|
258
|
+
SystemTimer.timeout(a_timeout) do
|
259
|
+
sleep 180
|
260
|
+
end
|
261
|
+
end
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
all_threads.each {|t| t.join}
|
266
|
+
end
|
267
|
+
|
268
|
+
def assert_timeout_within(expected_timeout_in_seconds,
|
269
|
+
error_margin = DEFAULT_ERROR_MARGIN,
|
270
|
+
&block)
|
271
|
+
start = Time.now
|
272
|
+
yield
|
273
|
+
flunk "Did not timeout as expected!"
|
274
|
+
rescue Timeout::Error
|
275
|
+
elapsed = Time.now - start
|
276
|
+
assert elapsed >= expected_timeout_in_seconds,
|
277
|
+
"Timed out too early, expected #{expected_timeout_in_seconds}, got #{elapsed} s"
|
278
|
+
assert elapsed < (expected_timeout_in_seconds + error_margin),
|
279
|
+
"Timed out after #{elapsed} seconds, expected #{expected_timeout_in_seconds}"
|
280
|
+
end
|
281
|
+
|
282
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/test_helper'
|
2
|
+
|
3
|
+
unit_tests do
|
4
|
+
|
5
|
+
test "timeout_after registers a new timer in the timer pool" do
|
6
|
+
pool = stub_everything
|
7
|
+
Thread.stubs(:current).returns(:the_current_thread)
|
8
|
+
SystemTimer.stubs(:timer_pool).returns(pool)
|
9
|
+
SystemTimer.stubs(:install_next_timer)
|
10
|
+
SystemTimer.stubs(:restore_original_configuration)
|
11
|
+
|
12
|
+
pool.expects(:add_timer).with(5, nil).returns(stub_everything)
|
13
|
+
SystemTimer.timeout_after(5) {}
|
14
|
+
end
|
15
|
+
|
16
|
+
test "timeout_after registers a new timer with a custom timeout exception in the timer pool" do
|
17
|
+
MyCustomException = Class.new(Exception)
|
18
|
+
pool = stub_everything
|
19
|
+
Thread.stubs(:current).returns(:the_current_thread)
|
20
|
+
SystemTimer.stubs(:timer_pool).returns(pool)
|
21
|
+
SystemTimer.stubs(:install_next_timer)
|
22
|
+
SystemTimer.stubs(:restore_original_configuration)
|
23
|
+
|
24
|
+
pool.expects(:add_timer).with(5, MyCustomException).returns(stub_everything)
|
25
|
+
SystemTimer.timeout_after(5, MyCustomException) {}
|
26
|
+
end
|
27
|
+
|
28
|
+
test "timeout_after installs a system timer saving the previous " +
|
29
|
+
"configuration when there is only one timer" do
|
30
|
+
|
31
|
+
now = Time.now
|
32
|
+
Time.stubs(:now).returns(now)
|
33
|
+
SystemTimer.stubs(:restore_original_configuration)
|
34
|
+
SystemTimer.expects(:install_first_timer_and_save_original_configuration) \
|
35
|
+
.with {|value| value.between?(23.99, 24.01) }
|
36
|
+
SystemTimer.timeout_after(24) {}
|
37
|
+
end
|
38
|
+
|
39
|
+
test "timeout_after installs a system timer without saving the previous " +
|
40
|
+
"configuration when there is more than one timer" do
|
41
|
+
|
42
|
+
now = Time.now
|
43
|
+
Time.stubs(:now).returns(now)
|
44
|
+
SystemTimer.timer_pool.register_timer now.to_f + 100, :a_thread
|
45
|
+
SystemTimer.stubs(:restore_original_configuration)
|
46
|
+
SystemTimer.stubs(:install_next_timer)
|
47
|
+
|
48
|
+
SystemTimer.expects(:install_next_timer) \
|
49
|
+
.with {|value| value.between?(23.99, 24.01) }
|
50
|
+
SystemTimer.timeout_after(24) {}
|
51
|
+
end
|
52
|
+
|
53
|
+
test "timeout_after installs a system timer with the interval before " +
|
54
|
+
"the next timer to expire" do
|
55
|
+
|
56
|
+
now = Time.now
|
57
|
+
Time.stubs(:now).returns(now)
|
58
|
+
SystemTimer.timer_pool.register_timer now.to_f + 24, :a_thread
|
59
|
+
SystemTimer.stubs(:restore_original_configuration)
|
60
|
+
SystemTimer.stubs(:install_next_timer)
|
61
|
+
|
62
|
+
SystemTimer.expects(:install_next_timer) \
|
63
|
+
.with {|value| value.between?(23.99, 24.01) }
|
64
|
+
SystemTimer.timeout_after(100) {}
|
65
|
+
end
|
66
|
+
|
67
|
+
test "timeout_after cancels the timer when the block completes without " +
|
68
|
+
"timeout" do
|
69
|
+
|
70
|
+
now = Time.now
|
71
|
+
the_timer = stub_everything
|
72
|
+
Time.stubs(:now).returns(now)
|
73
|
+
SystemTimer.stubs(:restore_original_configuration)
|
74
|
+
SystemTimer.stubs(:install_first_timer_and_save_original_configuration)
|
75
|
+
SystemTimer.timer_pool.stubs(:add_timer).returns(the_timer)
|
76
|
+
SystemTimer.timer_pool.stubs(:first_timer?).returns(true)
|
77
|
+
|
78
|
+
SystemTimer.timer_pool.expects(:cancel).with(the_timer)
|
79
|
+
SystemTimer.timeout_after(24) {}
|
80
|
+
end
|
81
|
+
|
82
|
+
test "debug does not output to stdout when debug is disabled" do
|
83
|
+
SystemTimer.stubs(:debug_enabled?).returns(false)
|
84
|
+
original_stdout = $stdout
|
85
|
+
begin
|
86
|
+
stdout = StringIO.new
|
87
|
+
$stdout = stdout
|
88
|
+
|
89
|
+
SystemTimer.send :debug, "a log message"
|
90
|
+
assert stdout.string.empty?
|
91
|
+
ensure
|
92
|
+
$stdout = original_stdout
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
test "debug logs messaget to stdout when debug is enabled" do
|
97
|
+
SystemTimer.stubs(:debug_enabled?).returns(true)
|
98
|
+
original_stdout = $stdout
|
99
|
+
begin
|
100
|
+
stdout = StringIO.new
|
101
|
+
$stdout = stdout
|
102
|
+
|
103
|
+
SystemTimer.send :debug, "a log message"
|
104
|
+
assert_match /a log message/, stdout.string
|
105
|
+
ensure
|
106
|
+
$stdout = original_stdout
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) + '/../lib'
|
2
|
+
$:.unshift File.dirname(__FILE__) + '/../ext/system_timer'
|
3
|
+
$: << File.dirname(__FILE__) + "/../vendor/gems/dust-0.1.6/lib"
|
4
|
+
$: << File.dirname(__FILE__) + "/../vendor/gems/mocha-0.9.1/lib"
|
5
|
+
require 'test/unit'
|
6
|
+
require 'dust'
|
7
|
+
require 'mocha'
|
8
|
+
require 'stringio'
|
9
|
+
require "open-uri"
|
10
|
+
require 'system_timer'
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: ghazel-SystemTimer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.2.1.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Philippe Hanrigou
|
8
|
+
- David Vollbracht
|
9
|
+
autorequire: system_timer
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
|
13
|
+
date: 2010-12-10 00:00:00 +00:00
|
14
|
+
default_executable:
|
15
|
+
dependencies: []
|
16
|
+
|
17
|
+
description:
|
18
|
+
email:
|
19
|
+
executables: []
|
20
|
+
|
21
|
+
extensions:
|
22
|
+
- ext/system_timer/extconf.rb
|
23
|
+
extra_rdoc_files:
|
24
|
+
- README
|
25
|
+
files:
|
26
|
+
- COPYING
|
27
|
+
- LICENSE
|
28
|
+
- ChangeLog
|
29
|
+
- ext/system_timer/system_timer_native.c
|
30
|
+
- ext/system_timer/extconf.rb
|
31
|
+
- lib/system_timer_stub.rb
|
32
|
+
- lib/system_timer/concurrent_timer_pool.rb
|
33
|
+
- lib/system_timer/thread_timer.rb
|
34
|
+
- lib/system_timer.rb
|
35
|
+
- test/all_tests.rb
|
36
|
+
- test/system_timer_unit_test.rb
|
37
|
+
- test/system_timer_functional_test.rb
|
38
|
+
- test/system_timer/concurrent_timer_pool_unit_test.rb
|
39
|
+
- test/system_timer/thread_timer_test.rb
|
40
|
+
- test/test_helper.rb
|
41
|
+
- README
|
42
|
+
has_rdoc: true
|
43
|
+
homepage:
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options:
|
48
|
+
- --title
|
49
|
+
- SystemTimer
|
50
|
+
- --main
|
51
|
+
- README
|
52
|
+
- --line-numbers
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project: systemtimer
|
70
|
+
rubygems_version: 1.3.5
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Set a Timeout based on signals, which are more reliable than Timeout. Timeout is based on green threads.
|
74
|
+
test_files:
|
75
|
+
- test/all_tests.rb
|