diff --git a/direct/src/showbase/GarbageReport.py b/direct/src/showbase/GarbageReport.py index 811b69444e..95c0e6137e 100755 --- a/direct/src/showbase/GarbageReport.py +++ b/direct/src/showbase/GarbageReport.py @@ -4,7 +4,6 @@ __all__ = ['FakeObject', '_createGarbage', 'GarbageReport', 'GarbageLogger'] from direct.directnotify.DirectNotifyGlobal import directNotify from direct.showbase.PythonUtil import gcDebugOn, safeRepr, fastRepr -#from direct.showbase.TaskThreaded import TaskThreaded, TaskThread from direct.showbase.Job import Job import gc @@ -26,18 +25,18 @@ class GarbageReport(Job): NotGarbage = 'NG' def __init__(self, name, log=True, verbose=False, fullReport=False, findCycles=True, - threaded=False, timeslice=None, doneCallback=None): + threaded=False, doneCallback=None): # if log is True, GarbageReport will self-destroy after logging # if false, caller is responsible for calling destroy() # if threaded is True, processing will be performed over multiple frames Job.__init__(self, name) - # stick the arguments onto a ScratchPad so we can access them from the thread - # functions and delete them all at once + # stick the arguments onto a ScratchPad so we can delete them all at once self._args = ScratchPad(name=name, log=log, verbose=verbose, fullReport=fullReport, findCycles=findCycles, doneCallback=doneCallback) self._printing = False jobMgr.add(self) - self.numGarbage = 0 + if threaded == False: + jobMgr.finish(self) def run(self): # do the garbage collection @@ -183,10 +182,20 @@ class GarbageReport(Job): yield None self._printing = False + yield Job.Done + + def suspend(self): + if self._printing: + self.notify.info('SUSPEND') + def resume(self): + if self._printing: + self.notify.info('RESUME') + + def finished(self): if self._args.doneCallback: self._args.doneCallback(self) - - yield Job.Done + if self._args.log: + self.destroy() def destroy(self): #print 'GarbageReport.destroy' @@ -204,13 +213,6 @@ class GarbageReport(Job): del self._reportStr Job.destroy(self) - def suspend(self): - if self._printing: - self.notify.info('SUSPEND') - def resume(self): - if self._printing: - self.notify.info('RESUME') - def getNumItems(self): return self.numGarbage diff --git a/direct/src/showbase/Job.py b/direct/src/showbase/Job.py index e2af54b5d1..1843a34bf2 100755 --- a/direct/src/showbase/Job.py +++ b/direct/src/showbase/Job.py @@ -6,6 +6,7 @@ class Job: Done = object() Continue = None # 'yield None' is acceptable in place of 'yield Job.Continue' + # these priorities are reference points, you can use whatever numbers you want Priorities = ScratchPad(Low=-100, Normal=0, High=100) _SerialGen = SerialNumGen() @@ -27,18 +28,21 @@ class Job: def getPriority(self): # override if you want a different priority - # you can use numbers other than those in Job.Priorities return Job.Priorities.Normal def suspend(self): # called when JobManager is going to stop running this job for a while - # most jobs don't need to override this pass def resume(self): # called when JobManager is going to start running this job again - # most jobs don't need to override this pass + def finished(self): + # called when the job finishes and has been removed from the JobManager + pass + + def getJobName(self): + return self._name def _getJobId(self): return self._id @@ -46,6 +50,9 @@ class Job: if self._generator is None: self._generator = self.run() return self._generator + def _cleanupGenerator(self): + if self._generator is not None: + self._generator = None if __debug__: # __dev__ not yet available at this point from direct.showbase.Job import Job diff --git a/direct/src/showbase/JobManager.py b/direct/src/showbase/JobManager.py index 75e18d0d01..f2f6903088 100755 --- a/direct/src/showbase/JobManager.py +++ b/direct/src/showbase/JobManager.py @@ -59,6 +59,8 @@ class JobManager: self._pri2jobIds[pri].remove(jobId) # remove the job from the main table del self._pri2jobId2job[pri][jobId] + # clean up the job's generator, if any + job._cleanupGenerator() if len(self._pri2jobId2job[pri]) == 0: del self._pri2jobId2job[pri] if pri == self._highestPriority: @@ -72,6 +74,31 @@ class JobManager: taskMgr.remove(JobManager.TaskName) self._highestPriority = 0 + def finish(self, job): + # run this job, right now, until it finishes + assert self.notify.debugCall() + jobId = job._getJobId() + # look up the job's priority + pri = self._jobId2pri[jobId] + # grab the job + job = self._pri2jobId2job[pri][jobId] + gen = job._getGenerator() + job.resume() + while True: + try: + result = gen.next() + except StopIteration: + # Job didn't yield Job.Done, it ran off the end and returned + # treat it as if it returned Job.Done + self.notify.warning('job %s never yielded Job.Done' % job) + result = Job.Done + if result is Job.Done: + job.suspend() + self.remove(job) + job.finished() + # job is done. + break + # how long should we run per frame? def getTimeslice(self): return self._timeslice @@ -104,6 +131,7 @@ class JobManager: if result is Job.Done: job.suspend() self.remove(job) + job.finished() # highest-priority job is done. # grab the next one if there's time left break