Pārlūkot izejas kodu

mark and sweep gc on removed doLaters

Joe Shochet 21 gadi atpakaļ
vecāks
revīzija
8477e70e0e
1 mainītis faili ar 22 papildinājumiem un 8 dzēšanām
  1. 22 8
      direct/src/task/Task.py

+ 22 - 8
direct/src/task/Task.py

@@ -312,7 +312,7 @@ class TaskManager:
         # Dictionary of priority to newTaskLists
         # Dictionary of priority to newTaskLists
         self.pendingTaskDict = {}
         self.pendingTaskDict = {}
         # List of tasks scheduled to execute in the future
         # List of tasks scheduled to execute in the future
-        self.doLaterList = []
+        self.__doLaterList = []
         self.currentTime, self.currentFrame = self.__getTimeFrame()
         self.currentTime, self.currentFrame = self.__getTimeFrame()
         if (TaskManager.notify == None):
         if (TaskManager.notify == None):
             TaskManager.notify = directNotify.newCategory("TaskManager")
             TaskManager.notify = directNotify.newCategory("TaskManager")
@@ -360,16 +360,25 @@ class TaskManager:
             tasks = filter(lambda task: not task.isRemoved(), tasks)
             tasks = filter(lambda task: not task.isRemoved(), tasks)
         return tasks
         return tasks
 
 
+    def __doLaterFilter(self):
+        # Filter out all the tasks that have been removed like a mark and
+        # sweep garbage collector. Returns the number of tasks that have
+        # been removed Warning: this creates an entirely new doLaterList.
+        oldLen = len(self.__doLaterList)
+        self.__doLaterList = filter(lambda task: not task.isRemoved(), self.__doLaterList)
+        newLen = len(self.__doLaterList)
+        return oldLen - newLen
+
     def __doLaterProcessor(self, task):
     def __doLaterProcessor(self, task):
         # Removing the tasks during the for loop is a bad idea
         # Removing the tasks during the for loop is a bad idea
         # Instead we just flag them as removed
         # Instead we just flag them as removed
         # Later, somebody else cleans them out
         # Later, somebody else cleans them out
-        while self.doLaterList:
+        while self.__doLaterList:
             # Check the first one on the list to see if it is ready
             # Check the first one on the list to see if it is ready
-            dl = self.doLaterList[0]
+            dl = self.__doLaterList[0]
             if dl.isRemoved():
             if dl.isRemoved():
                 # Get rid of this task forever
                 # Get rid of this task forever
-                heappop(self.doLaterList)
+                heappop(self.__doLaterList)
                 continue
                 continue
             # If the time now is less than the start of the doLater + delay
             # If the time now is less than the start of the doLater + delay
             # then we are not ready yet, continue to next one
             # then we are not ready yet, continue to next one
@@ -379,11 +388,16 @@ class TaskManager:
                 break
                 break
             else:
             else:
                 # Take it off the doLaterList, set its time, and make it pending
                 # Take it off the doLaterList, set its time, and make it pending
-                # TaskManager.notify.debug('__doLaterProcessor: spawning %s' % (dl))
-                heappop(self.doLaterList)
+
+                heappop(self.__doLaterList)
                 dl.setStartTimeFrame(self.currentTime, self.currentFrame)
                 dl.setStartTimeFrame(self.currentTime, self.currentFrame)
                 self.__addPendingTask(dl)
                 self.__addPendingTask(dl)
                 continue
                 continue
+        # Every nth pass, let's clean out the list of removed tasks
+        # This is basically a mark and sweep garbage collection of doLaters
+        if ((task.frame % 1000) == 0):
+            numRemoved = self.__doLaterFilter()
+            # TaskManager.notify.debug("filtered %s removed doLaters" % numRemoved)
         return cont
         return cont
 
 
     def doMethodLater(self, delayTime, func, taskName, extraArgs=None, uponDeath=None):
     def doMethodLater(self, delayTime, func, taskName, extraArgs=None, uponDeath=None):
@@ -407,7 +421,7 @@ class TaskManager:
         # Cache the time we should wake up for easier sorting
         # Cache the time we should wake up for easier sorting
         task.wakeTime = currentTime + delayTime
         task.wakeTime = currentTime + delayTime
         # Push this onto the doLaterList. The heap maintains the sorting.
         # Push this onto the doLaterList. The heap maintains the sorting.
-        heappush(self.doLaterList, task)
+        heappush(self.__doLaterList, task)
         if self.fVerbose:
         if self.fVerbose:
             # Alert the world, a new task is born!
             # Alert the world, a new task is born!
             messenger.send('TaskManager-spawnDoLater',
             messenger.send('TaskManager-spawnDoLater',
@@ -831,7 +845,7 @@ class TaskManager:
         # When we print, show the doLaterList in actual sorted order.
         # When we print, show the doLaterList in actual sorted order.
         # The priority heap is not actually in order - it is a tree
         # The priority heap is not actually in order - it is a tree
         # Make a shallow copy so we can sort it
         # Make a shallow copy so we can sort it
-        sortedDoLaterList = self.doLaterList[:]
+        sortedDoLaterList = self.__doLaterList[:]
         sortedDoLaterList.sort()
         sortedDoLaterList.sort()
         sortedDoLaterList.reverse()
         sortedDoLaterList.reverse()
         for task in sortedDoLaterList:
         for task in sortedDoLaterList: