Advertisement
Guest User

Untitled

a guest
Nov 17th, 2019
167
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 4.04 KB | None | 0 0
  1. package dijkstra
  2.  
  3. import kotlinx.atomicfu.atomic
  4. import java.util.*
  5. import java.util.concurrent.Phaser
  6. import java.util.concurrent.atomic.AtomicInteger
  7. import java.util.concurrent.locks.Lock
  8. import java.util.concurrent.locks.ReentrantLock
  9. import kotlin.Comparator
  10. import kotlin.collections.ArrayList
  11. import kotlin.concurrent.thread
  12. import kotlin.random.Random
  13.  
  14. private val NODE_DISTANCE_COMPARATOR = Comparator<Node> { o1, o2 -> Integer.compare(o1!!.distance, o2!!.distance) }
  15. private val DISTANCE_COMPARATOR = Comparator<Int> { o1, o2 -> o1.compareTo(o2) }
  16.  
  17.  
  18. class MultiQueue(val workers: Int, val comparator: java.util.Comparator<Node>) {
  19.     private val N = 10;
  20.     private val nonEmptyCnt = atomic(0)
  21.     private val queue: Array<PriorityQueue<Node>> = Array(N) { PriorityQueue<Node>(comparator) }
  22.     private val locks: Array<Lock> = Array(N) { ReentrantLock() }
  23.     fun add(node: Node) {
  24.         while (true) {
  25.             val qCnt = Random.nextInt(0, N)
  26.             if (locks[qCnt].tryLock()) {
  27.                 queue[qCnt].add(node)
  28.                 if (queue[qCnt].size == 1) {
  29.                     nonEmptyCnt.incrementAndGet()
  30.                 }
  31.                 locks[qCnt].unlock()
  32.                 return
  33.             }
  34.         }
  35.     }
  36.  
  37.     fun remove(): Node? {
  38.         loop@ while (true) {
  39.             if (nonEmptyCnt.compareAndSet(0, 0)) {
  40.                 return null
  41.             }
  42.             val f = Random.nextInt(0, N)
  43.             if (!locks[f].tryLock()) {
  44.                 continue;
  45.             }
  46.             val s = Random.nextInt(0, N)
  47.             if (!locks[s].tryLock()) {
  48.                 locks[f].unlock()
  49.                 continue
  50.             }
  51.             val res: Node;
  52.             if (queue[f].isEmpty() && queue[s].isEmpty()) {
  53.                 continue@loop
  54.             }
  55.             if (queue[f].isEmpty()) {
  56.                 return removedElement(s)
  57.             } else
  58.                 if (queue[s].isEmpty()) {
  59.                     return removedElement(f)
  60.                 } else
  61.                     if (queue[f].first().distance < queue[s].first().distance) {
  62.                         res = removedElement(f)
  63.                     } else {
  64.                         res = removedElement(s)
  65.                     }
  66.             locks[f].unlock()
  67.             locks[s].unlock()
  68.             return res
  69.         }
  70.     }
  71.  
  72.     private fun removedElement(i: Int): Node {
  73.         if (queue[i].size == 1) nonEmptyCnt.decrementAndGet()
  74.         return queue[i].remove()
  75.     }
  76.  
  77.  
  78.     val queues: List<PriorityQueue<Node>> = ArrayList(Collections.nCopies(N, PriorityQueue<Node>(comparator)))
  79.  
  80. }
  81.  
  82. /**
  83.  * Returns `Integer.MAX_VALUE` if a path has not been found.
  84.  */
  85. fun shortestPathParallel(start: Node) {
  86.     val workers = Runtime.getRuntime().availableProcessors()
  87.     val q = MultiQueue(workers, NODE_DISTANCE_COMPARATOR).apply {
  88.         add(start.apply {
  89.             distanceMutable.value = 0;
  90.         })
  91.     }
  92.  
  93.     val activeNodes = AtomicInteger(1)
  94.     val onFinish = Phaser(workers + 1)
  95.     repeat(workers) {
  96.         thread {
  97.             while (activeNodes.get() > 0) {
  98.                 q.remove()?.let { node ->
  99.                     val distance = node.distance
  100.                     for (edge in node.outgoingEdges) {
  101.                         val update = distance + edge.weight
  102.                         while (true) {
  103.                             val oldValue = edge.to.distance
  104.                             if (DISTANCE_COMPARATOR.compare(update, oldValue) >= 0) {
  105.                                 break
  106.                             }
  107.                             if (edge.to.distanceMutable.compareAndSet(oldValue, update)) {
  108.                                 q.add(edge.to)
  109.                                 activeNodes.incrementAndGet()
  110.                                 break
  111.                             }
  112.                         }
  113.                     }
  114.                     activeNodes.decrementAndGet()
  115.                 }
  116.             }
  117.             onFinish.arrive()
  118.         }
  119.     }
  120.     onFinish.arriveAndAwaitAdvance()
  121. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement