public
Fork of mojombo/god
Description: Ruby process monitor
Homepage: http://god.rubyforge.org
Clone URL: git://github.com/Bertg/god.git
redo timer mutexing
mojombo (author)
Mon Jan 07 15:25:08 -0800 2008
commit  063c7ed99d7b8597ae59fd337b3d7c3a81a81087
tree    4a2961535cfafdc92b2e54271c192333c4679c06
parent  0e1f9263ce16323bf0fd5c85f3113a42e90444d7
...
 
 
 
 
1
2
3
...
1
2
3
4
5
6
7
0
@@ -1,3 +1,7 @@
0
+== 0.6.6 / 2008-01-07
0
+ * Bug Fixes
0
+ * Redo Timer mutexing to reduce synchronization needs
0
+
0
 == 0.6.5 / 2008-01-04
0
   * Bug Fixes
0
     * Fix Timer descheduling deadlock issue
...
20
21
22
23
 
24
25
26
...
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
...
95
96
97
98
99
100
101
102
 
 
 
103
 
104
105
106
...
20
21
22
 
23
24
25
26
...
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
...
102
103
104
 
 
 
 
 
105
106
107
108
109
110
111
112
0
@@ -20,7 +20,7 @@ module God
0
   class Timer
0
     INTERVAL = 0.25
0
     
0
- attr_reader :events, :conditions, :timer
0
+ attr_reader :events, :pending_events, :conditions, :timer
0
     
0
     @@timer = nil
0
     
0
@@ -44,38 +44,45 @@ module God
0
     # Returns Timer
0
     def initialize
0
       @events = []
0
+ @pending_events = []
0
       @conditions = []
0
- @mutex = Monitor.new
0
+ @pending_mutex = Mutex.new
0
       
0
       @timer = Thread.new do
0
         loop do
0
           # applog(nil, :debug, "timer main loop, #{@events.size} events pending")
0
           
0
           begin
0
+ # pull in pending events
0
+ @pending_mutex.synchronize do
0
+ @pending_events.each { |e| @events << e }
0
+ @pending_events.clear
0
+ end
0
+
0
+ @events.sort! { |x, y| x.at <=> y.at }
0
+
0
             # get the current time
0
             t = Time.now.to_i
0
             
0
             # iterate over each event and trigger any that are due
0
- @mutex.synchronize do
0
- triggered = []
0
-
0
- @events.each do |event|
0
- if t >= event.at
0
- # trigger the event and mark it for removal
0
- self.trigger(event)
0
- triggered << event
0
- else
0
- # events are ordered, so we can bail on first miss
0
- break
0
- end
0
- end
0
-
0
- # remove all triggered events
0
- triggered.each do |event|
0
- @conditions.delete(event.condition)
0
- @events.delete(event)
0
+ triggered = []
0
+
0
+ @events.each do |event|
0
+ if t >= event.at
0
+ # trigger the event and mark it for removal
0
+ self.trigger(event)
0
+ triggered << event
0
+ else
0
+ # events are ordered, so we can bail on first miss
0
+ break
0
               end
0
             end
0
+
0
+ # remove all triggered events
0
+ triggered.each do |event|
0
+ @conditions.delete(event.condition)
0
+ @events.delete(event)
0
+ end
0
           rescue Exception => e
0
             message = format("Unhandled exception (%s): %s\n%s",
0
                              e.class, e.message, e.backtrace.join("\n"))
0
@@ -95,12 +102,11 @@ module God
0
     # Returns nothing
0
     def schedule(condition, delay = condition.interval)
0
       applog(nil, :debug, "timer schedule #{condition} in #{delay} seconds")
0
- @mutex.synchronize do
0
- unless @conditions.include?(condition)
0
- @events << TimerEvent.new(condition, delay)
0
- @conditions << condition
0
- @events.sort! { |x, y| x.at <=> y.at }
0
+ unless @conditions.include?(condition)
0
+ @pending_mutex.synchronize do
0
+ @pending_events << TimerEvent.new(condition, delay)
0
         end
0
+ @conditions << condition
0
       end
0
     end
0
     
...
13
14
15
16
 
17
18
19
...
13
14
15
 
16
17
18
19
0
@@ -13,7 +13,7 @@ class TestTimer < Test::Unit::TestCase
0
   def test_schedule_should_queue_event
0
     w = Watch.new
0
     @t.schedule(stub(:interval => 20, :watch => w))
0
-
0
+ sleep(0.3)
0
     assert_equal 1, @t.events.size
0
   end
0
   

Comments

    No one has commented yet.