Skip to content

Commit

Permalink
Stack with elimination implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
aartdem committed Mar 29, 2024
1 parent 5216e24 commit 7fb4d65
Show file tree
Hide file tree
Showing 6 changed files with 108 additions and 85 deletions.
17 changes: 2 additions & 15 deletions work1/src/main/kotlin/stack/Main.kt
Original file line number Diff line number Diff line change
@@ -1,21 +1,8 @@
package stack

import stack.simple.ConcurrentTreiberStack
import javax.print.attribute.standard.JobName
import kotlin.concurrent.thread
import kotlin.coroutines.coroutineContext
import stack.elimination.ConcurrentStackWithElimination

fun main() {
val st = ConcurrentTreiberStack<Int>()
val st = ConcurrentStackWithElimination<Int>()
st.push(1)
st.pop()

val threads = List(10) {
Thread {
println(Thread.currentThread().id)
}
}
threads.forEach { it.start() }

threads.forEach { it.join() }
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,32 @@ package stack.elimination

import stack.common.ConcurrentStack
import stack.common.Node
import java.util.concurrent.TimeoutException
import java.util.concurrent.atomic.AtomicReference
import java.util.concurrent.atomic.AtomicStampedReference

class EliminationArray<T>() {
fun visit(): T? {
TODO()
}
}

class ConcurrentStackWithElimination<T>(

) : ConcurrentStack<T> {
class ConcurrentStackWithElimination<T> : ConcurrentStack<T> {
private val head = AtomicReference<Node<T>?>()
private val eliminationArray = EliminationArray<T>()
override fun push(x: T) {
val newHead = Node(x)
while (true) {
if (tryPush(newHead)) return
eliminationArray.visit() ?: return
try {
eliminationArray.visit(x) ?: return
} catch (_: TimeoutException) {

}
}
}

override fun pop(): T? {
while (true) {
val (tryRes, valRes) = tryPop()
if (tryRes) return valRes
eliminationArray.visit()?.let {
return it
try {
eliminationArray.visit(null)?.let { return it }
} catch (_: TimeoutException) {

}
}
}
Expand Down
16 changes: 16 additions & 0 deletions work1/src/main/kotlin/stack/elimination/EliminationArray.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package stack.elimination

import kotlin.random.Random

class EliminationArray<T>(
private val capacity: Int = 100,
private val durationNanos: Long = 500_000_000,
randomSeed: Long = System.nanoTime(),
) {
private val random = Random(randomSeed)
private val exchanger = Array<LockFreeExchanger<T>>(capacity) { LockFreeExchanger() }
fun visit(value: T?): T? {
val slot = random.nextInt(capacity)
return exchanger[slot].exchange(value, durationNanos)
}
}
33 changes: 26 additions & 7 deletions work1/src/main/kotlin/stack/elimination/LockFreeExchanger.kt
Original file line number Diff line number Diff line change
@@ -1,27 +1,46 @@
package stack.elimination

import java.util.concurrent.TimeoutException
import java.util.concurrent.atomic.AtomicStampedReference

class LockFreeExchanger<T> {
private enum class State {
EMPTY, WAITING, BUSY
}

val slot: AtomicStampedReference<T?> = AtomicStampedReference(null, 0)
private val slot: AtomicStampedReference<T?> = AtomicStampedReference(null, 0)

fun exchange(myItem: T) {
fun exchange(myItem: T?, durationNanos: Long): T? {
val stampHolder = intArrayOf(State.EMPTY.ordinal)
val timeBound = System.nanoTime() + durationNanos
while (true) {
val anotherItem = slot.get(stampHolder) ?: TODO()
var currentItem = slot.get(stampHolder)
when (stampHolder[0]) {
State.EMPTY.ordinal -> {
if (slot.compareAndSet(anotherItem, myItem, State.EMPTY.ordinal, State.WAITING.ordinal)) {

if (slot.compareAndSet(currentItem, myItem, State.EMPTY.ordinal, State.WAITING.ordinal)) {
while (System.nanoTime() < timeBound) {
println("${System.nanoTime()} $timeBound")
currentItem = slot.get(stampHolder)
if (stampHolder[0] == State.BUSY.ordinal) {
slot.set(null, State.EMPTY.ordinal)
return currentItem
}
}
if (slot.compareAndSet(myItem, null, State.WAITING.ordinal, State.EMPTY.ordinal)) {
throw TimeoutException()
} else {
currentItem = slot.get(stampHolder)
slot.set(null, State.EMPTY.ordinal)
return currentItem
}
}
}

State.WAITING.ordinal -> {}
State.BUSY.ordinal -> {}
State.WAITING.ordinal -> {
if (slot.compareAndSet(currentItem, myItem, State.WAITING.ordinal, State.BUSY.ordinal)) {
return currentItem
}
}
}
}
}
Expand Down
50 changes: 0 additions & 50 deletions work1/src/test/kotlin/stack/ConcurrentStackTest.kt

This file was deleted.

53 changes: 53 additions & 0 deletions work1/src/test/kotlin/stack/ConcurrentStackTests.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package stack

import org.jetbrains.kotlinx.lincheck.annotations.Operation
import org.jetbrains.kotlinx.lincheck.check
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
import org.jetbrains.kotlinx.lincheck.strategy.stress.StressOptions
import stack.common.ConcurrentStack
import stack.elimination.ConcurrentStackWithElimination
import stack.simple.ConcurrentTreiberStack
import kotlin.test.Test

//abstract class ConcurrentStackTests(private val stack: ConcurrentStack<Int>) {
// @Operation
// fun push(value: Int) = stack.push(value)
//
// @Operation
// fun pop(): Int? = stack.pop()
//
// @Operation
// fun top(): Int? = stack.top()
//
// @Test
// fun stressTest() = StressOptions()
// .sequentialSpecification(SequentialStack::class.java)
// .check(this::class)
//
// @Test
// fun modelCheckingTest() = ModelCheckingOptions()
// .sequentialSpecification(SequentialStack::class.java)
// .checkObstructionFreedom()
// .check(this::class)
//
// @Test
// fun fourThreadsStressTest() = StressOptions()
// .sequentialSpecification(SequentialStack::class.java)
// .threads(4)
// .iterations(5)
// .invocationsPerIteration(100)
// .check(this::class)
//
// @Test
// fun fourThreadsModelCheckingTest() = ModelCheckingOptions()
// .sequentialSpecification(SequentialStack::class.java)
// .checkObstructionFreedom()
// .threads(4)
// .iterations(5)
// .invocationsPerIteration(100)
// .check(this::class)
//}

//class ConcurrentTreiberStackTests : ConcurrentStackTests(ConcurrentTreiberStack())

//class ConcurrentStackWithEliminationTests : ConcurrentStackTests(ConcurrentStackWithElimination())

0 comments on commit 7fb4d65

Please sign in to comment.