Advertisement
Guest User

Untitled

a guest
Nov 21st, 2019
97
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.39 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.         boolean destroyed = false;
  45.         synchronized (node) {
  46.             if (node.isLive()) {
  47.                 node.destroy();
  48.                 destroyed = true;
  49.             }
  50.         }
  51.         if (destroyed) {
  52.             findNeighboursToDestroy(node).stream()
  53.                     .map(DestroyingRunnable::new)
  54.                     .forEach(this::startTrackedThread);
  55.         }
  56.     }
  57.  
  58.     private List<Node> findNeighboursToDestroy(Node node) {
  59.         List<Node> neighboursToDestroy = new LinkedList<>();
  60.         for (Node neighbour : node.getNeighbours()) {
  61.             synchronized (neighbour) {
  62.                 if (neighbour.isLive() && damagePropagationInterface.destroyedBy(node.id, neighbour.id)) {
  63.                     neighbour.markToDestroy();
  64.                     neighboursToDestroy.add(neighbour);
  65.                 }
  66.             }
  67.         }
  68.         return neighboursToDestroy;
  69.     }
  70.  
  71.     private void startTrackedThread(DestroyingRunnable runnable) {
  72.         new Thread(new TrackingRunnable(runnable)).start();
  73.     }
  74.  
  75.     private class DestroyingRunnable implements Runnable {
  76.         private final Node node;
  77.  
  78.         private DestroyingRunnable(Node node) {
  79.             this.node = node;
  80.         }
  81.  
  82.         @Override
  83.         public void run() {
  84.             node.destroy();
  85.  
  86.             List<Node> neighboursToProcess = findNeighboursToDestroy(node);
  87.             if (!neighboursToProcess.isEmpty()) {
  88.                 neighboursToProcess.subList(1, neighboursToProcess.size()).stream()
  89.                         .map(DestroyingRunnable::new)
  90.                         .forEach(ChainReaction.this::startTrackedThread);
  91.  
  92.                 new DestroyingRunnable(neighboursToProcess.get(0)).run();
  93.             }
  94.         }
  95.     }
  96.  
  97.     private class TrackingRunnable implements Runnable {
  98.         private final Runnable runnable;
  99.  
  100.         private TrackingRunnable(Runnable runnable) {
  101.             this.runnable = runnable;
  102.         }
  103.  
  104.         @Override
  105.         public void run() {
  106.             try {
  107.                 synchronized (ChainReaction.this) {
  108.                     workingThreads++;
  109.                 }
  110.                 runnable.run();
  111.             } finally {
  112.                 synchronized (ChainReaction.this) {
  113.                     workingThreads--;
  114.                 }
  115.             }
  116.         }
  117.     }
  118.  
  119.     private static class Node {
  120.         private final int id;
  121.         private final List<Node> neighbours = new Vector<>();
  122.         private volatile NodeState state = NodeState.LIVE;
  123.  
  124.         private Node(int id) {
  125.             this.id = id;
  126.         }
  127.  
  128.         private List<Node> getNeighbours() {
  129.             return neighbours;
  130.         }
  131.  
  132.         private void addNeighbor(Node neighbor) {
  133.             neighbours.add(neighbor);
  134.         }
  135.  
  136.         private boolean isLive() {
  137.             return state == NodeState.LIVE;
  138.         }
  139.  
  140.         private boolean isDestroyed() {
  141.             return state == NodeState.DESTROYED;
  142.         }
  143.  
  144.         private void markToDestroy() {
  145.             state = NodeState.MARKED_TO_DESTROY;
  146.         }
  147.  
  148.         private void destroy() {
  149.             state = NodeState.DESTROYED;
  150.         }
  151.  
  152.         private enum NodeState {
  153.             LIVE, MARKED_TO_DESTROY, DESTROYED
  154.         }
  155.     }
  156. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement