Project

General

Profile

Feature #7086 ยป timeout-rk.rb

Program which tests a few alternative timeout implementations - rklemme (Robert Klemme), 09/30/2012 12:14 AM

 
1
#!/usr/local/bin/ruby19
2

    
3
require 'monitor'
4

    
5
Thread.abort_on_exception = true
6

    
7
# Process the given block in another thread (!) but at most the 
8
# given number of seconds.  If processing takes longer the result
9
# is discarded.
10
def timeout_1(timeout, &code)
11
  raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
12
  raise ArgumentError, "No code to execute" if code.nil?
13

    
14
  worker = Thread.new(&code)
15
  worker.join(timeout) and worker.value
16
end
17

    
18
# Process the given block in another thread (!) but at most the 
19
# given number of seconds.  If processing takes longer the result
20
# is discarded.
21
def timeout_2(timeout, &code)
22
  raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
23
  raise ArgumentError, "No code to execute" if code.nil?
24

    
25
  mon = Monitor.new
26
  cv = mon.new_cond
27

    
28
  worker = Thread.new do
29
      begin
30
        code.call
31
      ensure
32
        mon.synchronize { cv.signal }
33
      end
34
    end
35

    
36
  mon.synchronize do
37
    cv.wait(timeout)
38
  end ? worker.value : nil
39
end
40

    
41
# Process the given block in another thread (!) but at most the 
42
# given number of seconds.  If processing takes longer the result
43
# is discarded.
44
def timeout_3(timeout, &code)
45
  raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
46
  raise ArgumentError, "No code to execute" if code.nil?
47

    
48
  mon = Mutex.new
49
  cv = ::ConditionVariable.new
50

    
51
  worker = Thread.new do
52
      begin
53
        code.call
54
      ensure
55
        mon.synchronize { cv.signal }
56
      end
57
    end
58

    
59
  mon.synchronize do
60
    cv.wait(mon, timeout)
61
  end ? worker.value : nil
62
end
63

    
64
# Process the given block in another thread (!) but at most the 
65
# given number of seconds.  If processing takes longer the result
66
# is discarded.
67
def timeout_4(timeout, &code)
68
  raise ArgumentError, "Invalid timeout: %p" % [timeout] unless timeout > 0
69
  raise ArgumentError, "No code to execute" if code.nil?
70

    
71
  mon = Monitor.new
72
  cv = ::ConditionVariable.new
73

    
74
  worker = Thread.new do
75
      begin
76
        code.call
77
      ensure
78
        mon.synchronize { cv.signal }
79
      end
80
    end
81

    
82
  mon.synchronize do
83
    cv.wait(mon, timeout)
84
  end ? worker.value : nil
85
end
86

    
87
[1, 2, 4, 5].each do |sec|
88
  printf "Test with %2ds...\n", sec
89

    
90
  %w{timeout_1 timeout_2 timeout_3 timeout_4}.each do |meth|
91
    begin
92
      result = send meth, sec do
93
        sleep 3
94
        :success
95
      end
96

    
97
      printf "%-10s: %p", meth, result
98
      print " ERROR!" unless (sec > 3) == (result == :success)
99
      puts
100
    rescue Exception => e
101
      printf "ERROR: method %p: %p\n", meth, e
102
    end
103
  end
104

    
105
  puts
106
end
107

    
108