Advertisement
Iamnotagenius

Untitled

Nov 16th, 2024
113
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Kotlin 5.16 KB | None | 0 0
  1. import java.util.concurrent.*
  2. import java.util.concurrent.atomic.*
  3.  
  4. class FlatCombiningQueue<E> : Queue<E> {
  5.     private val queue = ArrayDeque<E>() // sequential queue
  6.     private val combinerLock = AtomicBoolean(false) // unlocked initially
  7.     private val tasksForCombiner = AtomicReferenceArray<Any?>(TASKS_FOR_COMBINER_SIZE)
  8.  
  9.     override fun enqueue(element: E) {
  10.         // TODO: Make this code thread-safe using the flat-combining technique.
  11.         // TODO: 1.  Try to become a combiner by
  12.         // TODO:     changing `combinerLock` from `false` (unlocked) to `true` (locked).
  13.         // TODO: 2a. On success, apply this operation and help others by traversing
  14.         // TODO:     `tasksForCombiner`, performing the announced operations, and
  15.         // TODO:      updating the corresponding cells to `Result`.
  16.         // TODO: 2b. If the lock is already acquired, announce this operation in
  17.         // TODO:     `tasksForCombiner` by replacing a random cell state from
  18.         // TODO:      `null` with the element. Wait until either the cell state
  19.         // TODO:      updates to `Result` (do not forget to clean it in this case),
  20.         // TODO:      or `combinerLock` becomes available to acquire.
  21.  
  22.         var cellIndex = randomCellIndex()
  23.         var isPut = false
  24.         while (true) {
  25.             if (combinerLock.compareAndSet(false, true)) {
  26.                 queue.addLast(element)
  27.                 if (isPut) {
  28.                     tasksForCombiner.set(cellIndex, null)
  29.                 }
  30.                 helpOthers()
  31.                 combinerLock.set(false)
  32.                 return
  33.             }
  34.  
  35.             if (!isPut) {
  36.                 if (tasksForCombiner.compareAndSet(cellIndex, null, element)) {
  37.                     isPut = true
  38.                 } else {
  39.                     cellIndex = randomCellIndex()
  40.                     continue
  41.                 }
  42.             }
  43.  
  44.             if (tasksForCombiner.get(cellIndex) == null) {
  45.                 return
  46.             }
  47.         }
  48.     }
  49.  
  50.     override fun dequeue(): E? {
  51.         // TODO: Make this code thread-safe using the flat-combining technique.
  52.         // TODO: 1.  Try to become a combiner by
  53.         // TODO:     changing `combinerLock` from `false` (unlocked) to `true` (locked).
  54.         // TODO: 2a. On success, apply this operation and help others by traversing
  55.         // TODO:     `tasksForCombiner`, performing the announced operations, and
  56.         // TODO:      updating the corresponding cells to `Result`.
  57.         // TODO: 2b. If the lock is already acquired, announce this operation in
  58.         // TODO:     `tasksForCombiner` by replacing a random cell state from
  59.         // TODO:      `null` with `Dequeue`. Wait until either the cell state
  60.         // TODO:      updates to `Result` (do not forget to clean it in this case),
  61.         // TODO:      or `combinerLock` becomes available to acquire.
  62.  
  63.         var cellIndex = randomCellIndex()
  64.         var isPut = false
  65.         var element: E? = null
  66.         while (true) {
  67.             if (combinerLock.compareAndSet(false, true)) {
  68.                 if (isPut) {
  69.                     val result = tasksForCombiner.getAndSet(cellIndex, null) as? Result<*>
  70.                     if (result != null) {
  71.                         element = result.value as E?
  72.                     } else {
  73.                         element = queue.removeFirstOrNull()
  74.                     }
  75.                 } else {
  76.                     element = queue.removeFirstOrNull()
  77.                 }
  78.                 helpOthers()
  79.                 combinerLock.set(false)
  80.                 return element
  81.             }
  82.  
  83.             if (!isPut) {
  84.                 if (tasksForCombiner.compareAndSet(cellIndex, null, Dequeue)) {
  85.                     isPut = true
  86.                 } else {
  87.                     cellIndex = randomCellIndex()
  88.                     continue
  89.                 }
  90.             }
  91.  
  92.             val result = tasksForCombiner.get(cellIndex) as? Result<*>
  93.             if (isPut && result != null) {
  94.                 tasksForCombiner.set(cellIndex, null)
  95.                 return result.value as E?
  96.             }
  97.         }
  98.     }
  99.  
  100.     fun helpOthers() {
  101.         for (i in 0..<tasksForCombiner.length()) {
  102.             if (tasksForCombiner.get(i) == null) {
  103.                 continue
  104.             }
  105.             if (tasksForCombiner.compareAndSet(i, Dequeue, Result(queue.firstOrNull()))) {
  106.                 queue.removeFirstOrNull()
  107.                 continue
  108.             }
  109.             var task = tasksForCombiner.get(i)
  110.             if (task is Result<*>) {
  111.                 continue
  112.             }
  113.             queue.addLast(task as E)
  114.             tasksForCombiner.set(i, null)
  115.         }
  116.     }
  117.  
  118.     private fun randomCellIndex(): Int =
  119.         ThreadLocalRandom.current().nextInt(tasksForCombiner.length())
  120. }
  121.  
  122. private const val TASKS_FOR_COMBINER_SIZE = 3 // Do not change this constant!
  123.  
  124. // TODO: Put this token in `tasksForCombiner` for dequeue().
  125. // TODO: enqueue()-s should put the inserting element.
  126. private object Dequeue
  127.  
  128. // TODO: Put the result wrapped with `Result` when the operation in `tasksForCombiner` is processed.
  129. private class Result<V>(
  130.     val value: V
  131. )
  132.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement