Threads
Engines tend to touch a model from three places at once. The ABI is built for that:
| Thread | Typical calls | Rule |
|---|---|---|
| tracking or network | ay2d_set_parameters, ay2d_set_part_opacities |
any thread, any time |
| render | ay2d_drawables, ay2d_mesh_geometry, ay2d_mesh_changes, ay2d_get_parameters |
any thread, any time |
| frame (game) | ay2d_update, motions, expressions, physics settings |
one thread at a time |
Any thread, any time covers setting values, reading the published result, and everything fixed at load (counts, ids, names, ranges, keys, groups, canvas, textures).
One thread at a time covers every call that drives the model: update,
ay2d_motion_*, ay2d_expression_*, ay2d_set_physics, ay2d_set_wind,
ay2d_reset_physics and the ay2d_add_* calls. If a second thread makes one
of these calls while the first is in one, it gets AY2D_STATUS_BUSY back
straight away and nothing changes. It does not wait, and nothing breaks.
Make these calls from one thread, usually your game loop, and you will
never see BUSY.
Render while updating. The model keeps two published results and takes turns. An update writes the back one and flips it to the front when done, so the render thread can keep drawing frame N while the frame thread works out frame N + 1.
Load and free are the only calls that must not overlap anything: load before any thread uses the model, free after every thread is done with it.