Advertisement
Guest User

Untitled

a guest
Nov 22nd, 2019
157
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 5.07 KB | None | 0 0
  1. import java.util.HashMap;
  2. import java.util.LinkedList;
  3. import java.util.List;
  4. import java.util.Map;
  5.  
  6. class ChainReaction implements ChainReactionInterface {
  7.     private final Map<Integer, Node> nodes = new HashMap<>();
  8.     private volatile int workingThreads = 0;
  9.     private volatile int initializations = 0;
  10.     private volatile boolean simulationStarted = false;
  11.     private DamagePropagationInterface damagePropagationInterface;
  12.  
  13.     @Override
  14.     public synchronized void addObject(int id) {
  15.         nodes.put(id, new Node(id));
  16.     }
  17.  
  18.     @Override
  19.     public synchronized void neighbour(int idA, int idB) {
  20.         if (idA != idB) {
  21.             Node nodeA = nodes.get(idA);
  22.             Node nodeB = nodes.get(idB);
  23.  
  24.             nodeA.addNeighbor(nodeB);
  25.             nodeB.addNeighbor(nodeA);
  26.         }
  27.     }
  28.  
  29.     @Override
  30.     public boolean resultReady() {
  31.         return simulationStarted && initializations == 0 && workingThreads == 0;
  32.     }
  33.  
  34.     @Override
  35.     public boolean isDestroyed(int id) {
  36.         return nodes.get(id).isDestroyed();
  37.     }
  38.  
  39.     @Override
  40.     public synchronized void setDamagePropagator(DamagePropagationInterface dpi) {
  41.         this.damagePropagationInterface = dpi;
  42.     }
  43.  
  44.     @Override
  45.     public void destroyed(int id) {
  46.         synchronized (this) {
  47.             initializations++;
  48.         }
  49.         simulationStarted = true;
  50.  
  51.         doInitialDestroy(id);
  52.  
  53.         synchronized (this) {
  54.             initializations--;
  55.         }
  56.     }
  57.  
  58.     private void doInitialDestroy(int id) {
  59.         Node node = nodes.get(id);
  60.  
  61.         if (node.isDestroyed()) {
  62.             return;
  63.         }
  64.         synchronized (node) {
  65.             if (node.isDestroyed()) {
  66.                 return;
  67.             }
  68.             node.destroy();
  69.         }
  70.  
  71.         findNeighboursToDestroy(node).stream()
  72.                 .map(DestroyingRunnable::new)
  73.                 .forEach(this::startTrackedThread);
  74.     }
  75.  
  76.     private List<Node> findNeighboursToDestroy(Node node) {
  77.         List<Node> neighboursToDestroy = new LinkedList<>();
  78.         for (Node neighbour : node.getNeighbours()) {
  79.             if (neighbour.isLive()) {
  80.                 synchronized (neighbour) {
  81.                     if (neighbour.isLive() && damagePropagationInterface.destroyedBy(node.id, neighbour.id)) {
  82.                         neighbour.markToDestroy();
  83.                         neighboursToDestroy.add(neighbour);
  84.                     }
  85.                 }
  86.             }
  87.         }
  88.         return neighboursToDestroy;
  89.     }
  90.  
  91.     private void startTrackedThread(DestroyingRunnable runnable) {
  92.         new Thread(new TrackingRunnable(runnable)).start();
  93.     }
  94.  
  95.     private class DestroyingRunnable implements Runnable {
  96.         private final Node node;
  97.  
  98.         private DestroyingRunnable(Node node) {
  99.             this.node = node;
  100.         }
  101.  
  102.         @Override
  103.         public void run() {
  104.             if (node.isDestroyed()) {
  105.                 return;
  106.             }
  107.             synchronized (node) {
  108.                 if (node.isDestroyed()) {
  109.                     return;
  110.                 }
  111.                 node.destroy();
  112.             }
  113.  
  114.             List<Node> neighboursToProcess = findNeighboursToDestroy(node);
  115.             if (!neighboursToProcess.isEmpty()) {
  116.                 neighboursToProcess.stream().skip(1)
  117.                         .map(DestroyingRunnable::new)
  118.                         .forEach(ChainReaction.this::startTrackedThread);
  119.  
  120.                 new DestroyingRunnable(neighboursToProcess.get(0)).run();
  121.             }
  122.         }
  123.     }
  124.  
  125.     private class TrackingRunnable implements Runnable {
  126.         private final Runnable runnable;
  127.  
  128.         private TrackingRunnable(Runnable runnable) {
  129.             this.runnable = runnable;
  130.         }
  131.  
  132.         @Override
  133.         public void run() {
  134.             try {
  135.                 synchronized (ChainReaction.this) {
  136.                     workingThreads++;
  137.                 }
  138.                 runnable.run();
  139.             } finally {
  140.                 synchronized (ChainReaction.this) {
  141.                     workingThreads--;
  142.                 }
  143.             }
  144.         }
  145.     }
  146.  
  147.     private static class Node {
  148.         private final int id;
  149.         private final List<Node> neighbours = new LinkedList<>();
  150.         private volatile NodeState state = NodeState.LIVE;
  151.  
  152.         private Node(int id) {
  153.             this.id = id;
  154.         }
  155.  
  156.         private List<Node> getNeighbours() {
  157.             return neighbours;
  158.         }
  159.  
  160.         private void addNeighbor(Node neighbor) {
  161.             neighbours.add(neighbor);
  162.         }
  163.  
  164.         private boolean isLive() {
  165.             return state == NodeState.LIVE;
  166.         }
  167.  
  168.         private boolean isDestroyed() {
  169.             return state == NodeState.DESTROYED;
  170.         }
  171.  
  172.         private void markToDestroy() {
  173.             state = NodeState.MARKED_TO_DESTROY;
  174.         }
  175.  
  176.         private void destroy() {
  177.             state = NodeState.DESTROYED;
  178.         }
  179.  
  180.         private enum NodeState {
  181.             LIVE, MARKED_TO_DESTROY, DESTROYED
  182.         }
  183.     }
  184. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement