Job.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. from direct.showbase.DirectObject import DirectObject
  2. if __debug__:
  3. from pandac.PandaModules import PStatCollector
  4. class Job(DirectObject):
  5. # Base class for cpu-intensive or non-time-critical operations that
  6. # are run through the JobManager.
  7. # values to yield from your run() generator method
  8. Done = object()
  9. Continue = None # 'yield None' is acceptable in place of 'yield Job.Continue'
  10. Sleep = object() # yield any remaining time for this job until next frame
  11. # These priorities determine how many timeslices a job gets relative to other
  12. # jobs. A job with priority of 1000 will run 10 times more often than a job
  13. # with priority of 100.
  14. Priorities = ScratchPad(Min=1, Low=100, Normal=1000, High=10000)
  15. _SerialGen = SerialNumGen()
  16. def __init__(self, name):
  17. self._name = name
  18. self._generator = None
  19. self._id = Job._SerialGen.next()
  20. self._printing = False
  21. self._priority = Job.Priorities.Normal
  22. self._finished = False
  23. if __debug__:
  24. self._pstats = PStatCollector("App:Show code:jobManager:%s" % self._name)
  25. def destroy(self):
  26. del self._name
  27. del self._generator
  28. del self._printing
  29. def getFinishedEvent(self):
  30. return 'job-finished-%s' % self._id
  31. def run(self):
  32. # this is a generator
  33. # override and do your processing
  34. # yield Job.Continue when possible/reasonable
  35. # try not to run longer than the JobManager's timeslice between yields
  36. #
  37. # when done, yield Job.Done
  38. #
  39. raise "don't call down"
  40. def getPriority(self):
  41. return self._priority
  42. def setPriority(self, priority):
  43. self._priority = priority
  44. def printingBegin(self):
  45. self._printing = True
  46. def printingEnd(self):
  47. self._printing = False
  48. def resume(self):
  49. # called every time JobManager is going to start running this job
  50. """
  51. if self._printing:
  52. # we may be suspended/resumed multiple times per frame, that gets spammy
  53. # if we need to pick out the output of a job, put a prefix onto each line
  54. # of the output
  55. print 'JOB:%s:RESUME' % self._name
  56. """
  57. pass
  58. def suspend(self):
  59. # called when JobManager is going to stop running this job for a while
  60. """
  61. if self._printing:
  62. #print 'JOB:%s:SUSPEND' % self._name
  63. pass
  64. """
  65. pass
  66. def _setFinished(self):
  67. self._finished = True
  68. self.finished()
  69. def isFinished(self):
  70. return self._finished
  71. def finished(self):
  72. # called when the job finishes and has been removed from the JobManager
  73. pass
  74. def getJobName(self):
  75. return self._name
  76. def _getJobId(self):
  77. return self._id
  78. def _getGenerator(self):
  79. if self._generator is None:
  80. self._generator = self.run()
  81. return self._generator
  82. def _cleanupGenerator(self):
  83. if self._generator is not None:
  84. self._generator = None
  85. if __debug__: # __dev__ not yet available at this point
  86. from direct.showbase.Job import Job
  87. class TestJob(Job):
  88. def __init__(self):
  89. Job.__init__(self, 'TestJob')
  90. self._counter = 0
  91. self._accum = 0
  92. self._finished = False
  93. def run(self):
  94. self.printingBegin()
  95. while True:
  96. while self._accum < 100:
  97. self._accum += 1
  98. print 'counter = %s, accum = %s' % (self._counter, self._accum)
  99. yield None
  100. self._accum = 0
  101. self._counter += 1
  102. if self._counter >= 100:
  103. print 'Job.Done'
  104. self.printingEnd()
  105. yield Job.Done
  106. else:
  107. yield None
  108. def addTestJob():
  109. jobMgr.add(TestJob())