Skip to content

Commit 46e41f2

Browse files
authored
Use nanosleep in runBlocking's delay on Native (#1228)
Fixes #1225
1 parent a3f150e commit 46e41f2

File tree

2 files changed

+23
-7
lines changed

2 files changed

+23
-7
lines changed

kotlinx-coroutines-core/native/src/Builders.kt

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44

55
package kotlinx.coroutines
66

7+
import kotlinx.cinterop.*
8+
import platform.posix.*
79
import kotlin.coroutines.*
810

911
/**
@@ -56,21 +58,24 @@ private class BlockingCoroutine<T>(
5658
get() = false // it throws exception to parent instead of cancelling it
5759

5860
@Suppress("UNCHECKED_CAST")
59-
fun joinBlocking(): T {
61+
fun joinBlocking(): T = memScoped {
6062
try {
6163
eventLoop?.incrementUseCount()
64+
val timespec = alloc<timespec>()
6265
while (true) {
6366
val parkNanos = eventLoop?.processNextEvent() ?: Long.MAX_VALUE
6467
// note: process next even may loose unpark flag, so check if completed before parking
6568
if (isCompleted) break
66-
// todo: LockSupport.parkNanos(this, parkNanos)
69+
timespec.tv_sec = parkNanos / 1000000000L // 1e9 ns -> sec
70+
timespec.tv_nsec = (parkNanos % 1000000000L).convert() // % 1e9
71+
nanosleep(timespec.ptr, null)
6772
}
6873
} finally { // paranoia
6974
eventLoop?.decrementUseCount()
7075
}
7176
// now return result
72-
val state = this.state
77+
val state = state
7378
(state as? CompletedExceptionally)?.let { throw it.cause }
74-
return state as T
79+
state as T
7580
}
7681
}

kotlinx-coroutines-core/native/test/DelayExceptionTest.kt

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
package kotlinx.coroutines
66

77
import kotlin.coroutines.*
8-
import kotlin.test.Test
9-
import kotlin.test.assertTrue
8+
import kotlin.test.*
109

11-
class DelayExceptionTest {
10+
class DelayExceptionTest : TestBase() {
1211
private object Dispatcher : CoroutineDispatcher() {
1312
override fun isDispatchNeeded(context: CoroutineContext): Boolean = true
1413
override fun dispatch(context: CoroutineContext, block: Runnable) { block.run() }
@@ -25,4 +24,16 @@ class DelayExceptionTest {
2524

2625
assertTrue(exception is IllegalStateException)
2726
}
27+
28+
@Test
29+
fun testMaxDelay() = runBlocking {
30+
expect(1)
31+
val job = launch {
32+
expect(2)
33+
delay(Long.MAX_VALUE)
34+
}
35+
yield()
36+
job.cancel()
37+
finish(3)
38+
}
2839
}

0 commit comments

Comments
 (0)