File tree 4 files changed +79
-12
lines changed
4 files changed +79
-12
lines changed Original file line number Diff line number Diff line change @@ -23,6 +23,9 @@ internal class LimitedDispatcher(
23
23
24
24
private val queue = LockFreeTaskQueue <Runnable >(singleConsumer = false )
25
25
26
+ // A separate object that we can synchronize on for K/N
27
+ private val workerAllocationLock = SynchronizedObject ()
28
+
26
29
@ExperimentalCoroutinesApi
27
30
override fun limitedParallelism (parallelism : Int ): CoroutineDispatcher {
28
31
parallelism.checkParallelism()
@@ -50,8 +53,7 @@ internal class LimitedDispatcher(
50
53
continue
51
54
}
52
55
53
- @Suppress(" CAST_NEVER_SUCCEEDS" )
54
- synchronized(this as SynchronizedObject ) {
56
+ synchronized(workerAllocationLock) {
55
57
-- runningWorkers
56
58
if (queue.size == 0 ) return
57
59
++ runningWorkers
@@ -87,8 +89,7 @@ internal class LimitedDispatcher(
87
89
}
88
90
89
91
private fun tryAllocateWorker (): Boolean {
90
- @Suppress(" CAST_NEVER_SUCCEEDS" )
91
- synchronized(this as SynchronizedObject ) {
92
+ synchronized(workerAllocationLock) {
92
93
if (runningWorkers >= parallelism) return false
93
94
++ runningWorkers
94
95
return true
Original file line number Diff line number Diff line change
1
+ /*
2
+ * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3
+ */
4
+
5
+ package kotlinx.coroutines
6
+
7
+ import kotlin.test.*
8
+
9
+ class LimitedParallelismSharedTest : TestBase () {
10
+ @Test
11
+ fun testTaskFairness () = runTest {
12
+ val view = Dispatchers .Default .limitedParallelism(1 )
13
+ val view2 = Dispatchers .Default .limitedParallelism(1 )
14
+ val j1 = launch(view) {
15
+ while (true ) {
16
+ yield ()
17
+ }
18
+ }
19
+ val j2 = launch(view2) { j1.cancel() }
20
+ joinAll(j1, j2)
21
+ }
22
+
23
+ @Test
24
+ fun testParallelismSpec () {
25
+ assertFailsWith<IllegalArgumentException > { Dispatchers .Default .limitedParallelism(0 ) }
26
+ assertFailsWith<IllegalArgumentException > { Dispatchers .Default .limitedParallelism(- 1 ) }
27
+ assertFailsWith<IllegalArgumentException > { Dispatchers .Default .limitedParallelism(Int .MIN_VALUE ) }
28
+ Dispatchers .Default .limitedParallelism(Int .MAX_VALUE )
29
+ }
30
+ }
Original file line number Diff line number Diff line change
1
+ /*
2
+ * Copyright 2016-2022 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3
+ */
4
+
5
+ import kotlinx.atomicfu.*
6
+ import kotlinx.coroutines.*
7
+ import kotlinx.coroutines.exceptions.*
8
+ import kotlin.test.*
9
+
10
+ class LimitedParallelismSharedStressTest : TestBase () {
11
+
12
+ private val targetParallelism = 4
13
+ private val iterations = 100_000
14
+ private val parallelism = atomic(0 )
15
+
16
+ private fun checkParallelism () {
17
+ val value = parallelism.incrementAndGet()
18
+ randomWait()
19
+ assertTrue { value <= targetParallelism }
20
+ parallelism.decrementAndGet()
21
+ }
22
+
23
+ @Test
24
+ fun testLimitedExecutor () = runMtTest {
25
+ val executor = newFixedThreadPoolContext(targetParallelism, " test" )
26
+ val view = executor.limitedParallelism(targetParallelism)
27
+ doStress {
28
+ repeat(iterations) {
29
+ launch(view) {
30
+ checkParallelism()
31
+ }
32
+ }
33
+ }
34
+ executor.close()
35
+ }
36
+
37
+ private suspend inline fun doStress (crossinline block : suspend CoroutineScope .() -> Unit ) {
38
+ repeat(stressTestMultiplier) {
39
+ coroutineScope {
40
+ block()
41
+ }
42
+ }
43
+ }
44
+ }
Original file line number Diff line number Diff line change @@ -11,14 +11,6 @@ import kotlin.test.*
11
11
12
12
class LimitedParallelismTest : TestBase () {
13
13
14
- @Test
15
- fun testParallelismSpec () {
16
- assertFailsWith<IllegalArgumentException > { Dispatchers .Default .limitedParallelism(0 ) }
17
- assertFailsWith<IllegalArgumentException > { Dispatchers .Default .limitedParallelism(- 1 ) }
18
- assertFailsWith<IllegalArgumentException > { Dispatchers .Default .limitedParallelism(Int .MIN_VALUE ) }
19
- Dispatchers .Default .limitedParallelism(Int .MAX_VALUE )
20
- }
21
-
22
14
@Test
23
15
fun testTaskFairness () = runTest {
24
16
val executor = newSingleThreadContext(" test" )
You can’t perform that action at this time.
0 commit comments