Guide

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.

Tracking, frame and render threads over time: sets never wait, updates write one frame while draws read the other

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.