In the game I’m working on, I’d like to run updates in stages: run several systems concurrently, with each publishing a message to an event/effect channel, then run each system again with just read access to the channel, and finally clearing the channel.
So I’d like something like Vec, in that I want to be able to push, iterate, and clear. In the first stage of the game update logic, multiple threads must push to the Vec-like type. Next, the vec is read from start to finish on each of the game system threads. Finally, the vec is cleared at the end of the game update stage.
I think that all I need is a type with an internal array and a
u8 current_index, and an unsafe method
atomic_push(&self, event: Event), which atomically-increments the index, then writes the event into the newly-claimed slot.
clear(&self) would then just erase all slots from 0 to
current_index, then reset
current_index to 0.
I think this is correct. I feel comfortable writing this. I even found the perfect method in unstable https://doc.rust-lang.org/stable/std/sync/atomic/struct.AtomicU32.html#method.fetch_add. I’m finding it difficult to locate concise docs on which CPUs would support this operation.
Crossbeam’s MPMC might be an alternative, but has the downside of popping messages off it seems. Multiple consumers need to read through the entire queue. Then a 3rd stage of the game update clears the whole queue.
There are other ways to accomplish this. This might be chasing performance in a way that’s not important, but I do expect this to be a hot area of code, and I’d like to learn about some of this plumbing anyway.