void MultithreadedIteration(int i)
{
//'i' is currently an index into an implicit array of solver updateables that goes from 0 to solverUpdateables.count * iterationLimit.
//It includes iterationLimit copies of each updateable.
//Permute the entire set with duplicates.
var updateable = solverUpdateables.Elements[(i * prime) % solverUpdateables.Count];
SolverSettings solverSettings = updateable.solverSettings;
//Updateables only ever go from active to inactive during iterations,
//so it's safe to check for activity before we do hard (synchronized) work.
if (updateable.isActiveInSolver)
{
int incrementedIterations = -1;
updateable.EnterLock();
//This duplicate test protects against the possibility that the updateable went inactive between the first check and the lock.
if (updateable.isActiveInSolver)
{
if (updateable.SolveIteration() < solverSettings.minimumImpulse)
{
solverSettings.iterationsAtZeroImpulse++;
if (solverSettings.iterationsAtZeroImpulse > solverSettings.minimumIterations)
updateable.isActiveInSolver = false;
}
else
{
solverSettings.iterationsAtZeroImpulse = 0;
}
//Increment the iteration count.
incrementedIterations = solverSettings.currentIterations++;
}
updateable.ExitLock();
//Since the updateables only ever go from active to inactive, it's safe to check outside of the lock.
//Keeping this if statement out of the lock allows other waiters to get to work a few nanoseconds faster.
if (incrementedIterations > iterationLimit ||
incrementedIterations > solverSettings.maximumIterations)
{
updateable.isActiveInSolver = false;
}
}
}