return time;
}
@Override
protected void nextStep() {
ICARulesModel m = this.getModel();
// get the grid from the model
ICARulesGrid grid = m.getGrid();
// update number of processors occasionally
procCountRefresh++;
if (procCountRefresh == 1000) {
Runtime r = Runtime.getRuntime();
procCount = r.availableProcessors();
// recompute the number of threads - if threadMult = 1.0 we'll have as
// many threads as physical resources, > 1 means that's there is the
// Probability to use more threads
procCount = (int) (procCount * threadCountFactor);
procCountRefresh = 0;
}
// list for the cells of which we computed new states
HashMap<int[], Integer> ccells = new HashMap<>();
// System.out.println("Going to use " + procs + " processors");
List<int[]> cells = new ArrayList<>(candidates.keySet());
// get the number of threads to be used right now, procsUsed = 0 is fine
// here, because we'll have automatically an "additional one" for the rest
int procsUsed = procCount;
while ((procsUsed * minNumberOfCellsPerThread > cells.size())
&& (procsUsed > 1)) {
procsUsed--;
}
int partition = cells.size() / procsUsed;
ComputeThread[] threads = new ComputeThread[procsUsed + 1];
// create a thread per partition
int p = 0;
for (int i = 0; i < procsUsed; i++) {
threads[i] = new ComputeThread(m, grid, cells, p, p + partition);
p += partition;
threads[i].start();
}
// create an extra thread for the rest of the division ("uncomplete"
// partition), if there is such a rest
if (p != cells.size()) {
threads[procsUsed] = new ComputeThread(m, grid, cells, p, cells.size());
threads[procsUsed].start();
}
// now wait until all threads have finished their job
try {
for (ComputeThread thread : threads) {
if (thread != null) {
thread.join();
ccells.putAll(thread.ccells);
}
}
} catch (InterruptedException e) {
SimSystem.report(e);
}
// empty the old list of cells to be updated, and let's refill it
this.candidates.clear();
// for all modified cells do
for (Map.Entry<int[], Integer> e : ccells.entrySet()) {
int current = m.getGrid().getState(e.getKey());
// update the cell's state
m.getGrid().setState(e.getValue(), e.getKey());
// remember the cell as to be updated in the next turn
this.candidates.put(e.getKey(), null);
// add all neighbour cells of the current cell to the list of cells to be
// computed in the next step
List<int[]> n =
m.getGrid().getNeighbors(m.getBaseRules().getNeighborhood(current),
m.getBaseRules().isTorus(current), e.getKey());
for (int i = 0; i < n.size(); i++) {
this.candidates.put(n.get(i), null);
}
}
m.changed();
// advance the time
time += 1;
changed();