I created a run loop in OpenGL ES which is called by a CADisplayLink at 60fps. AFAIK CADisplayLink calls it’s target on a background thread.
I have about 100 state variables which are used by the run loop.
The problem: From the main thread, I want to change state variables which are used in the run loop to draw something. A frame must be drawn only after all state variables have been set to their target values.
I am afraid that at some point when I change a state variable, and I’m not done yet changing them all (in one big method in same run loop iteration on main thread), for example position of a geometric shape, there is multi-threading related crash or problem where the CADisplayLink will kick in right in the middle of my method that updates the state variables, and then draw garbage or crash.
Obviously when I just use synchronized or atomic properties it won’t help because it is still not transactional. I think I need transactions.
My naive approach is this:
Instance variable read by run loop:
BOOL updatingState;
The run loop method will skip drawing if updatingState reads YES.
Then before starting to change state I set it to YES. And when everything is changed, I set it back to NO.
Now of course, problem: What if -while I am changing this- the run loop method is reading the values?
How do game engines deal with this problem? What kind of locking mechanisms do they have so the changing of the state variables can be finished before the next frame is going to be drawn?
You might find a read-copy-update strategy useful. One possible implementation is that each object actually contains two copies of the rendering parameters and an atomic flag is used to tell the rendering thread which to use. You will need to use a read memory barrier in the renderer to make sure that the flag is read before reading any of the parameters and a write memory barrier in the updater thread to make sure that all of the parameter updates are written before flipping the flag.