abort ();
}
}
- /* Here once_control->inited > 0. */
+ /* Here once_control->started == 0 and once_control->inited > 0. */
if (InterlockedDecrement (&once_control->num_threads) == 0)
- /* once_control->num_threads is now zero, and once_control->inited > 0.
+ /* once_control->num_threads is now zero, and
+ once_control->started == 0 and once_control->inited > 0.
No other thread will need to use the lock.
We can therefore destroy the lock, to free resources. */
/* If once_control->inited is == 1, set it to 2. */
* The first thread to go through the once_control->started fence
initializes the lock and moves inited from <= 0 to > 0. The other
threads don't move inited from <= 0 to > 0.
+ * started, once == 0, stays == 0.
* inited, once > 0, stays > 0 (since at the place where it is assigned 0,
it cannot be > 0).
* inited does not change any more once it is 2.
Therefore, it can be changed from 1 to 2 only once.
* DeleteCriticalSection gets invoked right after inited has been changed
from 1 to 2. Therefore, DeleteCriticalSection gets invoked only once.
- * After a moment where num_threads was 0 and inited was > 0, no thread can
- reach an InitializeCriticalSection or EnterCriticalSection invocation.
- Proof:
+ * After a moment where num_threads was 0 and started was 0 and
+ inited was > 0, no thread can reach an InitializeCriticalSection or
+ EnterCriticalSection invocation. Proof:
- At such a moment, no thread is in the code range between
InterlockedIncrement (&once_control->num_threads)
and
* From this it follows that:
- DeleteCriticalSection cannot be executed while the lock is taken
(because DeleteCriticalSection is only executed after a moment where
- num_threads was 0 and inited was > 0).
+ num_threads was 0 and started was 0 and inited was > 0).
- Once DeleteCriticalSection has been executed, the lock is not used any
more.
*/