protected internal void UnsafeSolveIteration(SolverUpdateable updateable) { if (updateable.isActiveInSolver) { SolverSettings solverSettings = updateable.solverSettings; solverSettings.currentIterations++; if (solverSettings.currentIterations <= iterationLimit && solverSettings.currentIterations <= solverSettings.maximumIterationCount) { if (updateable.SolveIteration() < solverSettings.minimumImpulse) { solverSettings.iterationsAtZeroImpulse++; if (solverSettings.iterationsAtZeroImpulse > solverSettings.minimumIterationCount) { updateable.isActiveInSolver = false; } } else { solverSettings.iterationsAtZeroImpulse = 0; } } else { updateable.isActiveInSolver = false; } } }
protected internal void UnsafePrestep(SolverUpdateable updateable) { updateable.UpdateSolverActivity(); if (updateable.isActiveInSolver) { SolverSettings solverSettings = updateable.solverSettings; solverSettings.currentIterations = 0; solverSettings.iterationsAtZeroImpulse = 0; updateable.Update(timeStepSettings.TimeStepDuration); } }
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[PermutationMapper.GetMappedIndex(i, 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.minimumIterationCount) { 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.maximumIterationCount) { updateable.isActiveInSolver = false; } } }