Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import java.util.HashMap;
- import java.util.LinkedList;
- import java.util.List;
- import java.util.Map;
- class ChainReaction implements ChainReactionInterface {
- private final Map<Integer, Node> nodes = new HashMap<>();
- private volatile int workingThreads = 0;
- private volatile int initializations = 0;
- private volatile boolean simulationStarted = false;
- private DamagePropagationInterface damagePropagationInterface;
- @Override
- public synchronized void addObject(int id) {
- nodes.put(id, new Node(id));
- }
- @Override
- public synchronized void neighbour(int idA, int idB) {
- if (idA != idB) {
- Node nodeA = nodes.get(idA);
- Node nodeB = nodes.get(idB);
- nodeA.addNeighbor(nodeB);
- nodeB.addNeighbor(nodeA);
- }
- }
- @Override
- public boolean resultReady() {
- return simulationStarted && initializations == 0 && workingThreads == 0;
- }
- @Override
- public boolean isDestroyed(int id) {
- return nodes.get(id).isDestroyed();
- }
- @Override
- public synchronized void setDamagePropagator(DamagePropagationInterface dpi) {
- this.damagePropagationInterface = dpi;
- }
- @Override
- public void destroyed(int id) {
- synchronized (this) {
- initializations++;
- }
- simulationStarted = true;
- doInitialDestroy(id);
- synchronized (this) {
- initializations--;
- }
- }
- private void doInitialDestroy(int id) {
- Node node = nodes.get(id);
- if (node.isDestroyed()) {
- return;
- }
- synchronized (node) {
- if (node.isDestroyed()) {
- return;
- }
- node.destroy();
- }
- findNeighboursToDestroy(node).stream()
- .map(DestroyingRunnable::new)
- .forEach(this::startTrackedThread);
- }
- private List<Node> findNeighboursToDestroy(Node node) {
- List<Node> neighboursToDestroy = new LinkedList<>();
- for (Node neighbour : node.getNeighbours()) {
- if (neighbour.isLive()) {
- synchronized (neighbour) {
- if (neighbour.isLive() && damagePropagationInterface.destroyedBy(node.id, neighbour.id)) {
- neighbour.markToDestroy();
- neighboursToDestroy.add(neighbour);
- }
- }
- }
- }
- return neighboursToDestroy;
- }
- private void startTrackedThread(DestroyingRunnable runnable) {
- new Thread(new TrackingRunnable(runnable)).start();
- }
- private class DestroyingRunnable implements Runnable {
- private final Node node;
- private DestroyingRunnable(Node node) {
- this.node = node;
- }
- @Override
- public void run() {
- if (node.isDestroyed()) {
- return;
- }
- synchronized (node) {
- if (node.isDestroyed()) {
- return;
- }
- node.destroy();
- }
- List<Node> neighboursToProcess = findNeighboursToDestroy(node);
- if (!neighboursToProcess.isEmpty()) {
- neighboursToProcess.stream().skip(1)
- .map(DestroyingRunnable::new)
- .forEach(ChainReaction.this::startTrackedThread);
- new DestroyingRunnable(neighboursToProcess.get(0)).run();
- }
- }
- }
- private class TrackingRunnable implements Runnable {
- private final Runnable runnable;
- private TrackingRunnable(Runnable runnable) {
- this.runnable = runnable;
- }
- @Override
- public void run() {
- try {
- synchronized (ChainReaction.this) {
- workingThreads++;
- }
- runnable.run();
- } finally {
- synchronized (ChainReaction.this) {
- workingThreads--;
- }
- }
- }
- }
- private static class Node {
- private final int id;
- private final List<Node> neighbours = new LinkedList<>();
- private volatile NodeState state = NodeState.LIVE;
- private Node(int id) {
- this.id = id;
- }
- private List<Node> getNeighbours() {
- return neighbours;
- }
- private void addNeighbor(Node neighbor) {
- neighbours.add(neighbor);
- }
- private boolean isLive() {
- return state == NodeState.LIVE;
- }
- private boolean isDestroyed() {
- return state == NodeState.DESTROYED;
- }
- private void markToDestroy() {
- state = NodeState.MARKED_TO_DESTROY;
- }
- private void destroy() {
- state = NodeState.DESTROYED;
- }
- private enum NodeState {
- LIVE, MARKED_TO_DESTROY, DESTROYED
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement