changeset 607:eab690c748a3

This is a more permanent fix for the timer issues. Pychan was using the timers incorrectly. This has now been fixed. It has eliminated the need to have global lists of timers in fife_timer. This has not been tested extensivly. [t:483]
author prock@33b003aa-7bff-0310-803a-e67f0ece8222
date Fri, 17 Sep 2010 19:55:15 +0000
parents a5c890f0e757
children c54f286a45fc
files engine/python/fife/extensions/fife_timer.py engine/python/fife/extensions/pychan/events.py
diffstat 2 files changed, 118 insertions(+), 37 deletions(-) [+]
line wrap: on
line diff
--- a/engine/python/fife/extensions/fife_timer.py	Thu Sep 16 16:46:17 2010 +0000
+++ b/engine/python/fife/extensions/fife_timer.py	Fri Sep 17 19:55:15 2010 +0000
@@ -27,22 +27,26 @@
 
 Usage::
   import fife.extensions.fife_timer
+  
   fife_timer.init( my_fife_engine.getTimeManager() )
+  
   def spam():
      print "SPAM SPAM ",
+  
   repeater = fife_timer.repeatCall(500,spam)
+  
   def stop_spam():
      repeater.stop()
      print "BACON EGGS AND SPAM"
-  fife_timer.delayCall(50000,stop_spam)
+  
+  delayed = fife_timer.delayCall(50000,stop_spam)
 
 """
 
 from fife import fife
 
+#global time manager
 _manager = None
-_alltimers = []
-_deadtimers = []
 
 def init(timemanager):
 	"""
@@ -59,11 +63,14 @@
 	
 	This class wraps the fife.TimeEvent class to make it easily usable from Python
 	It allows for a TimeEvent to be executed once or multiple times.
+	
+	Remember FIFE::TimeManager does NOT delete the timer so make sure you keep a reference 
+	to this timer to ensure python doesnt delete the timer prematurely.
 	"""
 	def __init__(self,delay=0,callback=None,repeat=0):
 		"""
 		@param delay: The delay in milliseconds to execute the callback
-		@param callback: The function to execute
+		@param callback: The function to execute when the time delay has passed
 		@param repeat: The number of times to execute the callback.  1=once, 0=forever 
 		"""
 		super(Timer,self).__init__(delay)
@@ -89,44 +96,19 @@
 		
 		self.setLastUpdateTime(self._manager.getTime())
 		self._manager.registerEvent(self)
-
-		global _alltimers
-		global _deadtimers
-		
-		_alltimers.append(self)
 		
 	def stop(self):
 		"""
 		Stops the timer
 		
-		This unregisters the timer from the time manager.  The time manager does NOT
-		delete the timer so make sure you keep a reference to this timer and ensure
-		python doesnt delete the timer prematurely.
+		This unregisters the timer from the time manager.  
 		"""
 		if not self._active:
 			return
 			
 		self._active = False
 		self._manager.unregisterEvent(self)
-
-
-		#FIXME: See ticket #483 in trac.  This is a temporary solution and needs
-		#to be reworked.
 		
-		global _alltimers
-		global _deadtimers
-		
-		#clean up any dead timers
-		del _deadtimers[:]
-
-		#Ddd this timer to the dead timers list to be removed next time a timer
-		#is stopped.
-		_deadtimers.append(self)
-
-		#finally remove self from the global timer list
-		_alltimers.remove(self)
-		
-
 	def updateEvent(self,delta):
 		"""
 		This is called by FIFE::TimeManager when the delay has passed.
@@ -141,11 +123,88 @@
 
 		if callable(self._callback):
 			self._callback()
-			
+
+	def _setDelay(self, delay):
+		"""
+		Sets how many milliseconds to wait before executing the callback.
+		
+		The timer must not be active to change this value
+		
+		@param delay: Number of milliseconds to wait before executing the callback.
+		@type delay: C{integer}
+		"""
+		
+		if not self._active:
+			self.setPeriod(delay)
+	
+	def _getDelay(self):
+		"""
+		Returns the number of milliseconds to wait before executing the callback.
+		
+		@return: Number of milliseconds.
+		@rtype: C{integer}
+		"""
+		return self.getPeriod()
+	
+	def _setCallback(self, callback):
+		self._callback = callback
+		
+	def _getCallback(self):
+		return self._callback
+	
+	def _setRepeat(self, repeat):
+		"""
+		Sets how many times the timer should be repeated.
+		
+		The timer must not be active to change it's repeat value.
+		
+		@param repeat: Number of times to repeat the timer.  0=forever, 1=once.
+		@type repeat: C{integer}
+		"""
+		
+		if not self._active:
+			self._repeat = repeat
+		
+	def _getRepeat(self, repeat):
+		"""
+		Returns the number of times the timer will be executed.
+		
+		@return: Number of times the timer will be executed.
+		@rtype: C{integer}
+		"""
+		return self._repeat
+	
+	def _getActive(self):
+		"""
+		Returns True if the timer is active and False if it is not.
+		
+		@return: True if timer is active, False if it is not.
+		@rtype: C{boolean}
+		"""
+		return self._active
+	
+	def _getNumExecuted(self):
+		"""
+		Returns the number of times the timer has been executed
+		
+		@return: Number of times the timer has been executed
+		@rtype: C{integer}
+		"""
+		return self._executed
+	
+	delay = property(_getDelay, _setDelay)
+	callback = property(_getCallback, _setCallback)
+	repeat = property(_getRepeat, _setRepeat)
+	active = property(_getActive)
+	numexecuted = property(_getNumExecuted)
+	
 
 def delayCall(delay,callback):
 	"""
 	Delay a function call by a number of milliseconds.
+	
+	Remember to keep a reference to the timer this function returns.  If you 
+	do not python will delete the timer prematurely which may case a segfault.
 
 	@param delay: Delay in milliseconds.
 	@param callback: The function to call.
@@ -162,6 +221,9 @@
 	"""
 	Repeat a function call. The call is repeated until the timer is stopped.
 
+	Remember to keep a reference to the timer this function returns.  If you 
+	do not python will delete the timer prematurely which may case a segfault.
+
 	@param period: Period between calls in milliseconds.
 	@param callback: The function to call.
 
--- a/engine/python/fife/extensions/pychan/events.py	Thu Sep 16 16:46:17 2010 +0000
+++ b/engine/python/fife/extensions/pychan/events.py	Fri Sep 17 19:55:15 2010 +0000
@@ -1,8 +1,8 @@
 # -*- coding: utf-8 -*-
 
 # ####################################################################
-#  Copyright (C) 2005-2009 by the FIFE team
-#  http://www.fifengine.de
+#  Copyright (C) 2005-2010 by the FIFE team
+#  http://www.fifengine.net
 #  This file is part of FIFE.
 #
 #  FIFE is free software; you can redistribute it and/or
@@ -67,7 +67,8 @@
 import tools
 import traceback
 import weakref
-from fife.extensions import fife_timer as timer
+from fife.extensions.fife_timer import Timer
+from fife.extensions.pychan.tools import callbackWithArguments as cbwa
 
 EVENTS = [
 	"mouseEntered",
@@ -105,6 +106,7 @@
 You passed None as parameter to %s.capture, which would normally remove a mapped event.
 But there was no event mapped. Did you accidently call a function instead of passing it?
 """
+
 class EventListenerBase(object):
 	"""
 	Redirector for event callbacks.
@@ -121,6 +123,9 @@
 		self.indent = 0
 		self.debug = get_manager().debug
 		self.is_attached = False
+		
+		self._timers = []
+		self._deadtimers = []		
 
 	def attach(self,widget):
 		"""
@@ -154,9 +159,22 @@
 			if name in self.events:
 				if self.debug: print "-"*self.indent, name
 				for f in self.events[name].itervalues():
-					def delayed_f():
+					def delayed_f(timer):
+						n_timer = timer()
 						f( event )
-					timer.delayCall(0,delayed_f)
+						
+#						del self._deadtimers[:]
+						
+						if n_timer in self._timers:
+#							self._deadtimers.append(n_timer)
+							self._timers.remove(n_timer)
+						
+							
+					timer = Timer(repeat=1)
+					timer._callback = cbwa(delayed_f, weakref.ref(timer))
+					timer.start()
+					
+					self._timers.append(timer)
 
 		except:
 			print name, repr(event)
@@ -327,4 +345,5 @@
 		raise exceptions.RuntimeError("Unknown event name: " + name)
 	if len(L) == 2:
 		L = L[0],L[1],"default"
-	return L
\ No newline at end of file
+	return L
+