Advertisement
Guest User

Untitled

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