there exists a tiny gap between finishing iterations of firing queued event and sm.op decrease
If another routine run internalFireQueued in that gap, it will not firing but save trigger in eventqueue and return.
Meanwhile, origin routine will not check event queue again because interations has finished
so such trigger event will be left in queue and wait for later firing trigger to executing.
If no trigger again, this trigger event will wait for ever and break run-to-complete
BTW, it's better not to execute all event in one loop,
which may cause Fire() caller waits for a long time to execute some actions not belong to current trigger.
So, in each loop, try to compare and swap sm.ops from 0 to 1, if failed, let current routine has chance to return.
there exists a tiny gap between finishing iterations of firing queued event and sm.op decrease
If another routine run internalFireQueued in that gap, it will not firing but save trigger in eventqueue and return.
Meanwhile, origin routine will not check event queue again because interations has finished
so such trigger event will be left in queue and wait for later firing trigger to executing. If no trigger again, this trigger event will wait for ever and break run-to-complete
BTW, it's better not to execute all event in one loop, which may cause Fire() caller waits for a long time to execute some actions not belong to current trigger. So, in each loop, try to compare and swap sm.ops from 0 to 1, if failed, let current routine has chance to return.