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