-
Notifications
You must be signed in to change notification settings - Fork 0
/
MutexExampleTests.kt
75 lines (66 loc) · 2.22 KB
/
MutexExampleTests.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package pt.isel.pc.problemsets.set3
import kotlinx.coroutines.TimeoutCancellationException
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withTimeout
import org.junit.jupiter.api.Test
import org.slf4j.Logger
import org.slf4j.LoggerFactory
import kotlin.test.assertFailsWith
class MutexExampleTests {
@Test
fun `suspending while holding a mutex behavior`() {
val mutex = Mutex()
suspend fun innerFunction() {
logger.info("suspending while holding a mutex")
delay(3000) // while suspended, this coroutine is holding the mutex
logger.info("after delay")
}
runBlocking {
launch {
mutex.withLock {
logger.info("'main' coroutine acquired the mutex")
innerFunction()
logger.info("'main' coroutine released the mutex")
}
}
delay(1000)
launch {
mutex.withLock {
logger.info("another coroutine acquired the mutex")
}
}
}
}
@Test
fun `mutex is not reentrant`() {
val mutex = Mutex()
suspend fun innerFunction() {
logger.info("a coroutine tries to acquire the mutex while holding it")
// without timeout, this coroutine would be suspended indefinitely
withTimeout(3000) {
mutex.withLock {
logger.info("supposedly unreachable code")
}
}
logger.info("after timeout")
}
runBlocking {
launch {
mutex.withLock {
logger.info("'main' coroutine acquired the mutex")
assertFailsWith<TimeoutCancellationException> {
innerFunction()
}
logger.info("'main' coroutine released the mutex")
}
}
}
}
companion object {
private val logger: Logger = LoggerFactory.getLogger(MutexExampleTests::class.java)
}
}