root/trunk/RBJabber/RBJabber/SubjectObserver/SchedulerSubject.py

Revision 528, 5.0 kB (checked in by sholloway, 5 years ago)

Depreciating WeakBind?, LazyProperty?
General cleanup tasks
Demo cleanups

Line 
1 #!/usr/bin/env python
2 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
3 ##~ License
4 ##~
5 ##- The RuneBlade Foundation library is intended to ease some
6 ##- aspects of writing intricate Jabber, XML, and User Interface (wxPython, etc.)
7 ##- applications, while providing the flexibility to modularly change the
8 ##- architecture. Enjoy.
9 ##~
10 ##~ Copyright (C) 2002  TechGame Networks, LLC.
11 ##~
12 ##~ This library is free software; you can redistribute it and/or
13 ##~ modify it under the terms of the BSD style License as found in the
14 ##~ LICENSE file included with this distribution.
15 ##~
16 ##~ TechGame Networks, LLC can be reached at:
17 ##~ 3578 E. Hartsel Drive #211
18 ##~ Colorado Springs, Colorado, USA, 80920
19 ##~
20 ##~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
21
22 """Subject/Observer like implementation of sched"""
23
24 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
25 #~ Imports
26 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
27
28 import bisect, time
29 from RBFoundation import BindCallable
30
31 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
32 #~ Definitions
33 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34
35 class SchedulerSubject(object):
36     def __init__(self, TimeFn=time.time):
37         self._TimeFn = BindCallable.BindCallable(TimeFn)
38         self._LastTime = 0
39         self._events = []
40        
41     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42     #~ Management
43     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
44    
45     def AddRelativeEvent(self, Time, observer):
46         return self.AddEvent(Time + self._TimeFn(), observer)
47
48     def AddEvent(self, Time, observer):
49         result = Time, BindCallable.BindCallable(observer)
50         bisect.insort(self._events, result)
51         return self
52
53     def RemoveEvent(self, observer):
54         result = BindCallable.BindCallable(observer)
55         self._events[:] = [x for x in self._events if x[-1] != result]
56         return self
57
58     def ClearEvents(self):
59         self._events[:] = []
60         return self
61
62     def Process(self, Time=None, LastTime=None):
63         if Time is None: Time = self._TimeFn()
64         LastTime, self._LastTime = self._LastTime, Time
65         return self.ProcessTimeWindow(LastTime, Time)
66
67     def ProcessTimeWindow(self, StartTime, StopTime):
68         result = []
69         for each in self._events:
70             if each[0] < StartTime: pass
71             elif each[0] <= StopTime:
72                 if each[1]: each[1](self, StopTime, each[0])
73             else: result.append(each)
74
75         self._events = result
76         return self._events and (self._events[-1][0] > StopTime)
77
78 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
79
80 class RecuringSchedulerSubject(SchedulerSubject):
81     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
82     #~ Update Callbacks
83     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
84    
85     def Reset(self, LastTime=0):
86         self._LastTime = LastTime
87
88     def ProcessTimeWindow(self, StartTime, StopTime):
89         result = []
90         for each in self._events:
91             if each[0] < StartTime: continue
92             elif each[0] <= StopTime:
93                 if each[1]: each[1](self, StopTime, each[0])
94             else: break
95
96         return self._events and (self._events[-1][0] > StopTime)
97
98 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
99 #~ Testing
100 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
101
102 def _Test_SchedulerSubject():
103     def printTime(scheduler, Time, EventTime):
104         print
105         print 'The time is now', time.ctime(Time),
106         if Time - EventTime  > 0.01:
107             print 'but was late by', Time - EventTime
108         else: print
109        
110     print
111     print "Testing time.time scheduler"
112     print
113     printTime(None, time.time(), time.time())
114
115     TimeSch = RecuringSchedulerSubject()
116     TimeSch.AddRelativeEvent(1.0, printTime)
117     TimeSch.AddRelativeEvent(2.0, printTime)
118     TimeSch.AddRelativeEvent(4.0, printTime)
119     TimeSch.AddRelativeEvent(8.0, printTime)
120
121     while TimeSch.Process():
122         time.sleep(0.2)
123         print '.',
124        
125     print "Do it Again?"
126     TimeSch.Reset()
127
128     while TimeSch.Process():
129         time.sleep(0.2)
130         print '.',
131        
132     #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
133
134     print
135     print "Testing tick scheduler"
136     print
137
138     def printTime(scheduler, tick, EventTime):
139         print 'The tick is now', tick,
140         if tick - EventTime > 0:
141             print 'but was scheduled for', EventTime
142         else: print
143        
144     global nTime
145     nTime = 0
146     def gettime(): return nTime
147    
148     TickSch = RecuringSchedulerSubject(gettime)
149     TickSch.AddRelativeEvent(5, printTime)
150     TickSch.AddRelativeEvent(20, printTime)
151     TickSch.AddRelativeEvent(40, printTime)
152
153     while TickSch.Process():
154         nTime += 1
155         print '.',
156     print "Doubletime!"
157     nTime = 0
158     TickSch.Reset()
159     while TickSch.Process():
160         nTime += 2
161         print '.',
162
163 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
164
165 if __name__=='__main__':
166     print "Testing..."
167     _Test_SchedulerSubject()
168     print "Test complete."
169
Note: See TracBrowser for help on using the browser.