libavg lets you work with several Python threads. However, calling libavg methods from secondary threads naively will not work and can cause crashes - you need to add some support code. This article explains the background and shows what to do if you have more than one thread.

Scheduling Calls

libavg provides an easy way to schedule execution of functions in the main thread from a secondary thread: callFromThread. For instance:

1  def moveNode(pos):
2      node.pos = pos
4  player.callFromThread(lambda: moveNode((30,0)))  

This causes moveNode to be executed in the main thread when timeouts are next processed, so you can call any libavg methods you want from moveNode.

Background: libavg and the Python Global Interpreter Lock

In normal Python execution, only one thread is running at a time. This is a general CPython issue: The interpreter uses a single Global Interpreter Lock (GIL - to serialize execution of Python code. However, there is no reason to disallow Python execution while libavg is rendering a frame, so libavg explicitly releases the lock when it starts rendering and re-aquires it when it's done rendering. The result is that secondary Python threads can run on another core while libavg is rendering, which is a Good Thing (in general).

The caveat is that if you call a libavg method from a secondary thread, you might be executing it while it's halfway through rendering. Depending on the exact circumstances (e.g. deleting a node while it's being rendered), this will often cause a crash. Thus, in general, you can't call libavg methods in secondary threads.