Advertisement
Guest User

Untitled

a guest
Oct 20th, 2019
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 4.67 KB | None | 0 0
  1. package dijkstra
  2.  
  3. import kotlinx.atomicfu.AtomicInt
  4. import kotlinx.atomicfu.atomic
  5. import java.util.*
  6. import java.util.Collections.nCopies
  7. import java.util.concurrent.Phaser
  8. import java.util.concurrent.atomic.AtomicInteger
  9. import kotlin.Comparator
  10. import kotlin.concurrent.thread
  11. import java.util.concurrent.locks.ReentrantLock
  12.  
  13. private val NODE_DISTANCE_COMPARATOR = Comparator<Node> { o1, o2 -> o1!!.distance.compareTo(o2!!.distance) }
  14.  
  15. private val random = Random()
  16.  
  17. // Returns `Integer.MAX_VALUE` if a path has not been found.
  18. fun shortestPathParallel(start: Node) {
  19.     val workers = Runtime.getRuntime().availableProcessors()
  20.     val elements = workers * 2
  21.     // The distance to the start node is `0`
  22.     start.distanceMutable.value = 0
  23.     // Create a priority (by distance) queue and add the start node into it
  24.     val queues = nCopies(elements, PriorityQueue(elements, NODE_DISTANCE_COMPARATOR))
  25.     val mutexes = nCopies(elements, ReentrantLock(true))
  26.     val activeNodes = AtomicInteger(0)
  27.     queues[0].add(start)
  28.     activeNodes.incrementAndGet()
  29.     // Run worker threads and wait until the total work is done
  30.     val onFinish = Phaser(workers + 1) // `arrive()` should be invoked at the end by each worker
  31.     repeat(workers) {
  32.         thread {
  33.             while (true) {
  34.                 // TODO Write the required algorithm here,
  35.                 // TODO break from this loop when there is no more node to process.
  36.                 // TODO Be careful, "empty queue" != "all nodes are processed".
  37.                 var cur: Node? = null
  38.                 while (activeNodes.get() > 0) {
  39.                     var firstInd = random.nextInt(elements)
  40.                     var secondInd = random.nextInt(elements)
  41.                     if (firstInd == secondInd) {
  42.                         continue
  43.                     }
  44.                     if (firstInd > secondInd) firstInd = secondInd.also { secondInd = firstInd }
  45.                     while (true) {
  46.                         mutexes[firstInd].lock()
  47.                         if (mutexes[secondInd].tryLock()) {
  48.                             break
  49.                         }
  50.                         mutexes[firstInd].unlock()
  51.                     }
  52.                     try {
  53.                         val firstNode: Node? = queues[firstInd].firstOrNull()
  54.                         val secondNode: Node? = queues[secondInd].firstOrNull()
  55.                         if (firstNode == null && secondNode == null) {
  56.                             continue
  57.                         }
  58.                         if (firstNode == null) {
  59.                             cur = queues[secondInd].poll()
  60.                             break
  61.                         }
  62.                         if (secondNode == null) {
  63.                             cur = queues[firstInd].poll()
  64.                             break
  65.                         }
  66.                         cur = if (firstNode.distance < secondNode.distance) {
  67.                             queues[firstInd].poll()
  68.                         } else {
  69.                             queues[secondInd].poll()
  70.                         }
  71.                         break
  72.                     } finally {
  73.                         mutexes[secondInd].unlock()
  74.                         mutexes[firstInd].unlock()
  75.                     }
  76.                 }
  77.                 if (cur == null) {
  78. //                    if (activeNodes.get() == 0) {
  79.                         break
  80. //                    } else {
  81. //                        continue
  82. //                    }
  83.                 }
  84.                 var distE: Int
  85.                 for (e in cur.outgoingEdges) {
  86.                     distE = e.to.distance
  87.                     while (distE > cur.distance + e.weight) {
  88.                         if (e.to.distanceMutable.compareAndSet(distE, cur.distance + e.weight)) {
  89.                             while (true) {
  90.                                 val index = random.nextInt(elements)
  91.                                 if (mutexes[index].tryLock()) {
  92.                                     try {
  93.                                         activeNodes.incrementAndGet()
  94.                                         queues[index].add(e.to)
  95.                                         break
  96.                                     } finally {
  97.                                         mutexes[index].unlock()
  98.                                     }
  99.                                 }
  100.                             }
  101.                         }
  102.                         distE = e.to.distance
  103.                     }
  104.                 }
  105.                 activeNodes.decrementAndGet()
  106.             }
  107.             onFinish.arrive()
  108.         }
  109.     }
  110.     onFinish.arriveAndAwaitAdvance()
  111. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement