Advertisement
Guest User

Untitled

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