1 # ###################################################
2 # Copyright (C) 2008 The OpenAnno Team
4 # This file is part of OpenAnno.
6 # OpenAnno is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 2 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program; if not, write to the
18 # Free Software Foundation, Inc.,
19 # 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20 # ###################################################
23 from game
.util
import livingObject
, WeakMethod
26 class Scheduler(livingObject
):
27 """"Class providing timed callbacks.
28 To start a timed callback, call add_new_object() to make the TimingThread Class create a CallbackObject for you.
29 @param timer: Timer instance the schedular registers itself with.
31 def begin(self
, timer
):
32 super(Scheduler
, self
).begin()
36 self
.timer
.add_call(self
.tick
)
38 def tick(self
, tick_id
):
40 @param tick_id: int id of the tick.
42 self
.cur_tick
= tick_id
43 if self
.cur_tick
in self
.schedule
:
44 for callback
in self
.schedule
[self
.cur_tick
]:
46 assert callback
.loops
>= -1
47 if callback
.loops
is not 0:
48 self
.add_object(callback
) # readd object
49 del self
.schedule
[self
.cur_tick
]
50 assert (len(self
.schedule
) == 0) or self
.schedule
.keys()[0] > self
.cur_tick
52 def add_object(self
, callback_obj
):
53 """Adds a new CallbackObject instance to the callbacks list
54 @param callback_obj: CallbackObject type object, containing all neccessary information
56 if not (self
.cur_tick
+ callback_obj
.runin
) in self
.schedule
:
57 self
.schedule
[self
.cur_tick
+ callback_obj
.runin
] = []
58 if callback_obj
.loops
> 0:
59 callback_obj
.loops
-= 1
60 self
.schedule
[self
.cur_tick
+ callback_obj
.runin
].append(callback_obj
)
62 def add_new_object(self
, callback
, class_instance
, runin
=1, loops
=1):
63 """Creates a new CallbackObject instance and calls the self.add_object() function.
64 @param callback: lambda function callback, which is called runin ticks.
65 @param class_instance: class instance the function belongs to.
66 @param runin: int number of ticks after which the callback is called. Standard is 1, run next tick.
67 @param loops: How often the callback is called. -1 = infinit times. Standard is 1, run once."""
69 callback_obj
= CallbackObject(self
, callback
, class_instance
, runin
, loops
)
70 self
.add_object(callback_obj
)
72 def rem_object(self
, callback_obj
):
73 """Removes a CallbackObject from all callback lists
74 @param callback_obj: CallbackObject to remove
76 for key
in self
.schedule
:
77 for i
in xrange(0, self
.schedule
[key
].count(callback_obj
)):
78 self
.schedule
[key
].remove(callback_obj
)
81 #TODO: Check if this is still necessary for weak referenced objects
82 def rem_all_classinst_calls(self
, class_instance
):
83 """Removes all callbacks from the scheduler that belong to the class instance class_inst."""
84 for key
in self
.schedule
:
85 for callback_obj
in self
.schedule
[key
]:
86 if callback_obj
.class_instance
is class_instance
:
87 self
.schedule
[key
].remove(callback_obj
)
89 def rem_call(self
, instance
, callback
):
90 """Removes all callbacks of 'instance' that are 'callback'
91 @param instance: the instance that would execute the call
92 @param callback: the function to remove
94 for key
in self
.schedule
:
95 for callback_obj
in self
.schedule
[key
]:
96 if callback_obj
.class_instance() is instance
and callback_obj
.callback
== WeakMethod(callback
):
97 self
.schedule
[key
].remove(callback_obj
)
101 self
._is
_ended
= True
102 self
.timer
.remove_call(self
.tick
)
105 class CallbackObject(object):
106 """Class used by the TimerManager Class to organize callbacks."""
107 def __init__(self
, scheduler
, callback
, class_instance
, runin
=1, loops
=1):
108 """Creates the CallbackObject instance.
109 @param scheduler: reference to the scheduler, necessary to react properly on weak reference callbacks
110 @param callback: lambda function callback, which is called runin ticks.
111 @param class_instance: class instance the original function(not the lambda function!) belongs to.
112 @param runin: int number of ticks after which the callback is called. Standard is 1, run next tick.
113 @param loops: How often the callback is called. -1 = infinit times. Standard is 1, run once.
114 @param weakref_aciton: A callback to register with the weak reference
117 # Do some input validation, otherwise errors occure long after wrong data was added
120 raise ValueError("Can't schedule callbacks in the past, runin must be a positive number")
122 if (loops
< -1) or (loops
is 0):
123 raise ValueError("Loop count must be a positive number or -1 for infinite repeat")
125 self
.callback
= WeakMethod(callback
)
127 # Check for persisting strong references
130 if (class_instance
in gc
.get_referents(self
.callback
)):
132 raise ValueError("callback has strong reference to class_instance")
134 self
.scheduler
= scheduler
137 self
.class_instance
= weakref
.ref(class_instance
, lambda ref
: self
.scheduler
.rem_object(self
))