mirror of
https://github.com/panda3d/panda3d.git
synced 2025-10-04 10:54:24 -04:00
handle job never returning Job.Done, allow yield None instead of yield Job.Continue, added suspend/resume
This commit is contained in:
parent
89b2d71e56
commit
ac9c7274f6
@ -1,8 +1,11 @@
|
||||
class Job:
|
||||
# Base class for cpu-intensive or non-time-critical operations that
|
||||
# are run through the JobManager.
|
||||
|
||||
# values to yield from your run() generator method
|
||||
Done = object()
|
||||
Continue = object()
|
||||
Continue = None # 'yield None' is acceptable in place of 'yield Job.Continue'
|
||||
|
||||
Priorities = ScratchPad(Low=-100, Normal=0, High=100)
|
||||
_SerialGen = SerialNumGen()
|
||||
|
||||
@ -15,16 +18,26 @@ class Job:
|
||||
del self._name
|
||||
del self._generator
|
||||
|
||||
def run(self):
|
||||
# override and do your processing
|
||||
# yield Job.Continue when possible/reasonable
|
||||
# try not to run longer than the JobManager's timeslice between yields
|
||||
# when done, yield Job.Done
|
||||
raise "don't call down"
|
||||
|
||||
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 run(self):
|
||||
# override and yield Job.Continue when possible/reasonable
|
||||
# try not to run longer than the JobManager's timeslice between yields
|
||||
# when done, yield Job.Done
|
||||
raise "don't call down"
|
||||
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 _getJobId(self):
|
||||
return self._id
|
||||
@ -48,7 +61,7 @@ if __debug__: # __dev__ not yet available at this point
|
||||
while self._accum < 100:
|
||||
self._accum += 1
|
||||
print 'counter = %s, accum = %s' % (self._counter, self._accum)
|
||||
yield Job.Continue
|
||||
yield None
|
||||
|
||||
self._accum = 0
|
||||
self._counter += 1
|
||||
@ -57,9 +70,7 @@ if __debug__: # __dev__ not yet available at this point
|
||||
print 'Job.Done'
|
||||
yield Job.Done
|
||||
else:
|
||||
yield Job.Continue
|
||||
yield None
|
||||
|
||||
def addTestJob():
|
||||
t = TestJob()
|
||||
jobMgr.add(t)
|
||||
|
||||
jobMgr.add(TestJob())
|
||||
|
@ -6,11 +6,11 @@ class JobManager:
|
||||
"""
|
||||
Similar to the taskMgr but designed for tasks that are CPU-intensive and/or
|
||||
not time-critical. Jobs run one at a time, in order of priority, in
|
||||
the timeslice that the JobManager is allowed to run each frame.
|
||||
the timeslice that the JobManager is allotted each frame.
|
||||
"""
|
||||
notify = directNotify.newCategory("JobManager")
|
||||
|
||||
# there's one main task for the JobManager, all jobs run in this task
|
||||
# there's one task for the JobManager, all jobs run in this task
|
||||
TaskName = 'jobManager'
|
||||
# run for one millisecond per frame by default
|
||||
DefTimeslice = .001
|
||||
@ -85,14 +85,24 @@ class JobManager:
|
||||
endT = globalClock.getRealTime() + (self._timeslice * .9)
|
||||
while True:
|
||||
# always process the highest priority first
|
||||
# TODO: give occasional timeslices to lower priorities to avoid starving
|
||||
# lower-priority jobs
|
||||
jobId2job = self._pri2jobId2job[self._highestPriority]
|
||||
# process jobs with equal priority in the order they came in
|
||||
jobId = self._pri2jobIds[self._highestPriority][-1]
|
||||
job = jobId2job[jobId]
|
||||
gen = job._getGenerator()
|
||||
job.resume()
|
||||
while globalClock.getRealTime() < endT:
|
||||
result = gen.next()
|
||||
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)
|
||||
# highest-priority job is done.
|
||||
# grab the next one if there's time left
|
||||
@ -100,9 +110,10 @@ class JobManager:
|
||||
else:
|
||||
# we've run out of time
|
||||
assert self.notify.debug('out of time: %s, %s' % (endT, globalClock.getRealTime()))
|
||||
job.suspend()
|
||||
break
|
||||
|
||||
if len(self._pri2jobId2job) == 0:
|
||||
# there's nothing left to do
|
||||
# there's nothing left to do, all the jobs are done!
|
||||
break
|
||||
return task.cont
|
||||
|
Loading…
x
Reference in New Issue
Block a user