mirror of
https://github.com/Sneed-Group/Poodletooth-iLand
synced 2024-12-25 12:42:41 -06:00
149 lines
4.9 KiB
Python
149 lines
4.9 KiB
Python
"""Undocumented Module"""
|
|
|
|
__all__ = ['TaskThreaded', 'TaskThread']
|
|
|
|
from direct.directnotify.DirectNotifyGlobal import directNotify
|
|
from direct.task import Task
|
|
|
|
class TaskThreaded:
|
|
""" derive from this if you need to do a bunch of CPU-intensive
|
|
processing and you don't want to hang up the show. Lets you break
|
|
up the processing over multiple frames """
|
|
notify = directNotify.newCategory("TaskThreaded")
|
|
|
|
_Serial = SerialNumGen()
|
|
|
|
def __init__(self, name, threaded=True, timeslice=None, callback=None):
|
|
# timeslice is how long this thread should take every frame.
|
|
self.__name = name
|
|
self.__threaded=threaded
|
|
if timeslice is None:
|
|
timeslice = .01
|
|
self.__timeslice = timeslice
|
|
self.__taskNames = set()
|
|
self._taskStartTime = None
|
|
self.__threads = set()
|
|
self._callback = callback
|
|
|
|
def finished(self):
|
|
if self._callback:
|
|
self._callback()
|
|
|
|
def destroy(self):
|
|
for taskName in self.__taskNames:
|
|
taskMgr.remove(taskName)
|
|
del self.__taskNames
|
|
for thread in self.__threads:
|
|
thread.tearDown()
|
|
thread._destroy()
|
|
del self.__threads
|
|
del self._callback
|
|
self.ignoreAll()
|
|
|
|
def getTimeslice(self):
|
|
return self.___timeslice
|
|
def setTimeslice(self, timeslice):
|
|
self.__timeslice = timeslice
|
|
|
|
def scheduleCallback(self, callback):
|
|
assert self.notify.debugCall()
|
|
if not self.__threaded:
|
|
callback()
|
|
else:
|
|
taskName = ('%s-ThreadedTask-%s' %
|
|
(self.__name, TaskThreaded._Serial.next()))
|
|
assert taskName not in self.__taskNames
|
|
self.__taskNames.add(taskName)
|
|
taskMgr.add(Functor(self.__doCallback, callback, taskName),
|
|
taskName)
|
|
|
|
def scheduleThread(self, thread):
|
|
assert self.notify.debugCall()
|
|
# pass in a TaskThread. TaskThreaded will take over ownership and
|
|
# cleanup responsibilities
|
|
thread._init(self)
|
|
thread.setUp()
|
|
if thread.isFinished():
|
|
thread._destroy()
|
|
else:
|
|
if not self.__threaded:
|
|
while not thread.isFinished():
|
|
thread.run()
|
|
thread._destroy()
|
|
else:
|
|
assert not thread in self.__threads
|
|
self.__threads.add(thread)
|
|
taskName = ('%s-ThreadedTask-%s-%s' %
|
|
(self.__name, thread.__class__.__name__,
|
|
TaskThreaded._Serial.next()))
|
|
assert taskName not in self.__taskNames
|
|
self.__taskNames.add(taskName)
|
|
self.__threads.add(thread)
|
|
taskMgr.add(Functor(self._doThreadCallback, thread, taskName),
|
|
taskName)
|
|
|
|
def _doCallback(self, callback, taskName, task):
|
|
assert self.notify.debugCall()
|
|
self.__taskNames.remove(taskName)
|
|
self._taskStartTime = globalClock.getRealTime()
|
|
callback()
|
|
self._taskStartTime = None
|
|
return Task.done
|
|
|
|
def _doThreadCallback(self, thread, taskName, task):
|
|
assert self.notify.debugCall()
|
|
self._taskStartTime = globalClock.getRealTime()
|
|
thread.run()
|
|
self._taskStartTime = None
|
|
if thread.isFinished():
|
|
thread._destroy()
|
|
self.__taskNames.remove(taskName)
|
|
self.__threads.remove(thread)
|
|
return Task.done
|
|
else:
|
|
return Task.cont
|
|
|
|
def taskTimeLeft(self):
|
|
"""returns True if there is time left for the current task callback
|
|
to run without going over the allotted timeslice"""
|
|
if self._taskStartTime is None:
|
|
# we must not be in a task callback, we must be running in non-threaded
|
|
# mode
|
|
return True
|
|
return (globalClock.getRealTime() - self._taskStartTime) < self.__timeslice
|
|
|
|
class TaskThread:
|
|
# derive and override these four funcs
|
|
# TaskThreaded obj is available as 'self.parent'
|
|
# attributes of TaskThreaded obj are available directly as self.variable
|
|
# call self.finished() when you're done
|
|
def setUp(self):
|
|
pass
|
|
def run(self):
|
|
pass
|
|
def tearDown(self):
|
|
# undo what you did in setUp()
|
|
# this will be called if we get destroyed early
|
|
pass
|
|
def done(self):
|
|
# override this if you want to do stuff after the thread finishes
|
|
pass
|
|
|
|
# call this when your task is complete
|
|
def finished(self):
|
|
self.tearDown()
|
|
self._finished = True
|
|
self.done()
|
|
def isFinished(self):
|
|
return self._finished
|
|
|
|
# call this to find out if you've gone over your timeslice
|
|
def timeLeft(self):
|
|
return self.parent.taskTimeLeft()
|
|
|
|
def _init(self, parent):
|
|
self.parent = parent
|
|
self._finished = False
|
|
def _destroy(self):
|
|
del self.parent
|
|
del self._finished
|