Skip to content

Commit 55235d8

Browse files
committed
WIP
1 parent e812e65 commit 55235d8

File tree

8 files changed

+44
-44
lines changed

8 files changed

+44
-44
lines changed

atomicfu/build.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ kotlin {
119119

120120
jvmTest {
121121
dependencies {
122-
implementation("org.jetbrains.kotlinx:lincheck:2.35")
122+
implementation("org.jetbrains.kotlinx:lincheck:2.38")
123123
implementation("org.jetbrains.kotlin:kotlin-reflect")
124124
implementation("org.jetbrains.kotlin:kotlin-test")
125125
implementation("org.jetbrains.kotlin:kotlin-test-junit")

atomicfu/src/concurrentMain/kotlin/kotlinx/atomicfu/locks/Mutex.kt

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ package kotlinx.atomicfu.locks
22

33
import kotlinx.atomicfu.AtomicRef
44
import kotlinx.atomicfu.atomic
5-
import kotlinx.atomicfu.parking.ThreadParker
5+
import kotlinx.atomicfu.parking.KThread
6+
import kotlinx.atomicfu.parking.Parker
67
import kotlinx.atomicfu.parking.currentThreadId
78

89
internal class NativeMutex {
@@ -62,7 +63,7 @@ internal class NativeMutex {
6263
// Remove head
6364
if (newState > 1) {
6465
val prevNode = parkingQueue.enqueue()
65-
prevNode.parker.park()
66+
prevNode.nodeWait()
6667
parkingQueue.dequeue()
6768
owningThread.value = currentThreadId
6869
holdCount.incrementAndGet()
@@ -87,7 +88,7 @@ internal class NativeMutex {
8788
// If waiters wake up the first in line. The woken up thread will dequeue the node.
8889
if (currentState > 0) {
8990
val nextParker = parkingQueue.getHead()
90-
nextParker.parker.unpark()
91+
nextParker.nodeWake()
9192
return
9293
}
9394
}
@@ -144,7 +145,35 @@ internal class NativeMutex {
144145
}
145146

146147
private class Node {
147-
val parker = ThreadParker()
148+
val parker = atomic<Any>(Empty)
148149
val next = atomic<Node?>(null)
150+
151+
fun nodeWait() {
152+
while (true) {
153+
when (parker.value) {
154+
Empty -> if (parker.compareAndSet(Empty, KThread.currentThread())) Parker.park()
155+
is KThread -> Parker.park()
156+
Woken -> return
157+
}
158+
}
159+
}
160+
161+
fun nodeWake() {
162+
while (true) {
163+
when (val currentState = parker.value) {
164+
Empty -> if (parker.compareAndSet(Empty, Woken)) return
165+
is KThread -> if (parker.compareAndSet(currentState, Woken)) {
166+
Parker.unpark(currentState)
167+
return
168+
}
169+
Woken -> throw IllegalStateException("Node is already woken")
170+
}
171+
}
172+
}
149173
}
174+
175+
private object Empty
176+
private object Woken
177+
178+
150179
}

atomicfu/src/concurrentMain/kotlin/kotlinx/atomicfu/parking/ThreadParker.kt

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,15 @@ import kotlin.time.TimeSource.Monotonic
77
/**
88
* Multiplatform thread parker.
99
*/
10-
internal class ThreadParker {
10+
internal class ThreadParker(private val owningThread: KThread) {
1111
private val delegator = ParkingDelegator
1212
private val state = atomic<ParkingState>(Free)
1313

14-
fun park() = parkWith({ false }) { data ->
15-
delegator.wait(data) { state.value is Parked }
14+
fun park() {
15+
check(owningThread == KThread.currentThread()) { "Parking on other threads parker" }
16+
parkWith({ false }) { data ->
17+
delegator.wait(data) { state.value is Parked }
18+
}
1619
}
1720

1821
fun parkNanos(nanos: Long) {

atomicfu/src/jvmMain/kotlin/kotlinx/atomicfu/parking/KThread.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package kotlinx.atomicfu.parking
22

33
actual class KThread internal actual constructor() {
4-
internal val parker = ThreadParker()
4+
internal val parker = ThreadParker(this)
55
actual companion object {
66
actual fun currentThread(): KThread = localKThread.get()
77
}

atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/locks/NativeMutexLincheckReentrantTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import kotlinx.atomicfu.locks.NativeMutex
2-
import org.jetbrains.kotlinx.lincheck.LoggingLevel
32
import org.jetbrains.kotlinx.lincheck.annotations.Operation
43
import org.jetbrains.kotlinx.lincheck.check
54
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
5+
import org.jetbrains.kotlinx.lincheck.util.LoggingLevel
66
import kotlin.test.Test
77

88
class NativeMutexLincheckReentrantTest {

atomicfu/src/jvmTest/kotlin/kotlinx/atomicfu/locks/NativeMutexLincheckTest.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import kotlinx.atomicfu.locks.NativeMutex
2-
import org.jetbrains.kotlinx.lincheck.LoggingLevel
32
import org.jetbrains.kotlinx.lincheck.annotations.Operation
43
import org.jetbrains.kotlinx.lincheck.check
54
import org.jetbrains.kotlinx.lincheck.strategy.managed.modelchecking.ModelCheckingOptions
5+
import org.jetbrains.kotlinx.lincheck.util.LoggingLevel
66
import kotlin.test.Test
77

88
class NativeMutexLincheckTest {

atomicfu/src/nativeMain/kotlin/kotlinx/atomicfu/parking/KThread.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ package kotlinx.atomicfu.parking
33
import kotlinx.atomicfu.atomic
44

55
actual class KThread internal actual constructor() {
6-
internal val parker: ThreadParker = ThreadParker()
6+
internal val parker: ThreadParker = ThreadParker(this)
77
actual companion object {
88
actual fun currentThread(): KThread = thisKThread
99
}

atomicfu/src/nativeUnixLikeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt

Lines changed: 0 additions & 32 deletions
This file was deleted.

0 commit comments

Comments
 (0)