Task.py __executeTask and arguments

Hi,

Let me start by saying I may be in a little over my head as far as understanding the code goes.

What I am attempting to do, is build a reactor for twisted that would allow it to interface with pandas main loop.

I am assuming that i should use tasks to do this. My problems is this;

The method wrapper that is being passed into the TaskManager instance does not accept any arguments. After my reactor passes a few calls to taskmanager it will die due to receiving 1 instead of 0 args. I have worked around this successfully by modifying __executeTask to look something like this:

    def __executeTask(self, task):
        task.setCurrentTimeFrame(self.currentTime, self.currentFrame)
        if not self.taskTimerVerbose:
            startTime = self.trueClock.getShortTime()
            # don't record timing info
            if task.name == 'twisted':
                ret = task()
            else:
                ret = task(*task.extraArgs)

            endTime = self.trueClock.getShortTime()
            
            # Record the dt
            dt = endTime - startTime
            task.dt = dt

where ‘twisted’ is the name of the task.

This works thus far. My questions are:

  1. Why is it sometimes passing arguments to task() and sometimes not?
  2. Is there an existing way to prevent it from passing these arguments?
  3. If not, what would the best way be to prevent this while keeping the panda codebase unmolested?

I hope i’ve made everything clear, please let me know if you have any questions or suggestions. Thanks :smiley:
edit: for title clarity

The arguments passed is basically 1: the task:
you must always return task.cont to have the task continue, or task.done to make the task stop.
You can also do task.time to check how long the task was already running.

def __init__(self):
  taskMgr.add(self.twisted,"twisted")
def twisted(self,task):
   # do something
   return task.cont #continue running

You can also specify in the taskMgr.add call that extra arguments are passed to the task. However, if you specify nothing there, you will only need the task parameter.

Thanks for the quick reply.

Returning None appears to be the same as returning done or exit, which is convenient as i the method i’m placing into the tasks list is essentially out of my control, unless i wanted to molest the twisted framework which i don’t.

What i’m doing more specifically is (from internet._threadedselect.py in twisted):

"The waker function (in this case taskMgr.add())
will be called from a “background” thread with one argument: func.
The waker function’s purpose is to call func() from the main thread.
Many GUI toolkits ship with appropriate waker functions.
Some examples of this are wxPython’s wx.callAfter (may be wxCallAfter in
older versions of wxPython) or PyObjC’s PyObjCTools.AppHelper.callAfter.
"

My issue is that when this function is finally executed by the scheduler, it’s adding arguments to it causing it to bomb out.

Granted, I may be doing this in a backwards or in a completely incorrect manner due to ignorance of both panda and twisted XD but it does appear to be working for now.

Still, i would like to know if there’s a more specific way to control __executeTask in place, or perhaps another way to work around this without having to modify the panda codebase.

I have messed around with the optional arguments to TaskManager.add() but they didn’t have any noticable affect nor did the doMethodLater method seeing as they all call __executeTask eventually.

Thanks again! I hope i’ve made things a bit clearer.

Hmm, interesting.
You could create a task function which calls the appropriate function:

def __init__(self):
  taskMgr.add(self.callFunc,"myTask")
def callFunc(self,task):
  return myActualFunctionWithoutArguments()
    def _runInMainThread(self, f):
        if hasattr(self, "pandaApp"):
            #taskMgr.add(f,"twisted")
            self.f = f
            taskMgr.add(self.taskWrapper, 'taskWrapper') 
        else:
            self._postQueue.put(f)
    def taskWrapper(self, task):
        self.f()
        return None

That’s the ticket. Thanks a bunch. :slight_smile: I’ll post the rest of the code once i get signal handling taken care of and get it cleaned up a bit.