Pay no attention to those classes in the API reference; they’re very low-level. There are much better high-level tools for threading your tasks, which are (as you have noted) as yet unfortunately undocumented.
In a nutshell, the idea is to create a new “task chain”. As of Panda3D 1.6, the task manager manages tasks in one or more “task chains”. By default, all tasks go onto the default task chain, but you can have any number of separate task chains. Each task chain is a linear list of tasks, and each task chain can be in its own thread.
So, to create a threaded task, you only need to do:
taskMgr.setupTaskChain('myTaskChainName', numThreads = 1)
taskMgr.add(self.myTask, 'myTask', taskChain = 'myTaskChainName')
Now myTask will run in its own thread, independent of the default task chain which runs in the main thread. There are some implications with running a task in a thread.
(1) You can’t call base.graphicsEngine.renderFrame() from a sub-thread. You shouldn’t try, it might appear to work, but it’s bad.
(2) You have to protect yourself from race conditions with synchronization primitives, provided in direct.stdpy.threading. If you’re not already familiar with standard threading synchronization primitives, there are plenty of resources on the net to learn about them–it’s a wide field of study, and I can’t possibly describe it in a forum post.
(3) You have to call Thread.considerYield() from time to time. Panda threads are (as built by default) semi-cooperative, which has the advantage that it protects you from many of the dangers of getting (2) wrong, but it does mean you can block other threads indefinitely by failing to call Thread.considerYield() frequently enough.
(4) When you send a message via messenger.send(), you can arrange for the receiver to hear the message on your current thread (the default behavior) or on the thread of another taskChain, by passing taskChain = ‘otherTaskChainName’ on the send() call. The default, main task chain is called ‘default’.
(5) Pausing a thread means blocking it, via a synchronization primitive such as a condition variable or a semaphore.
If you’re not already very comfortable with threading, though, I don’t really recommend diving into it unless there really is no other way to solve your problem. Threading is a very tricky business, it’s real easy to get wrong, and real hard to debug when it is wrong.