Skip to content

Commit 84bce48

Browse files
turing-techqwwdfsad
authored andcommitted
Properly use acquired permits in Semaphore
Fixes #1423
1 parent 65f1eaf commit 84bce48

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

kotlinx-coroutines-core/common/src/sync/Semaphore.kt

+1-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ private class SemaphoreImpl(
9696
* and the maximum number of waiting acquirers cannot be greater than 2^31 in any
9797
* real application.
9898
*/
99-
private val _availablePermits = atomic(permits)
99+
private val _availablePermits = atomic(permits - acquiredPermits)
100100
override val availablePermits: Int get() = max(_availablePermits.value, 0)
101101

102102
// The queue of waiting acquirers is essentially an infinite array based on `SegmentQueue`;

kotlinx-coroutines-core/common/test/sync/SemaphoreTest.kt

+32-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
package kotlinx.coroutines.sync
22

3-
import kotlinx.coroutines.TestBase
4-
import kotlinx.coroutines.cancelAndJoin
5-
import kotlinx.coroutines.launch
6-
import kotlinx.coroutines.yield
3+
import kotlinx.coroutines.*
74
import kotlin.test.Test
85
import kotlin.test.assertEquals
96
import kotlin.test.assertFalse
@@ -140,4 +137,35 @@ class SemaphoreTest : TestBase() {
140137
job1.cancel()
141138
finish(6)
142139
}
140+
141+
@Test
142+
fun testAcquiredPermits() = runTest {
143+
val semaphore = Semaphore(5, acquiredPermits = 4)
144+
assertEquals(semaphore.availablePermits, 1)
145+
semaphore.acquire()
146+
assertEquals(semaphore.availablePermits, 0)
147+
assertFalse(semaphore.tryAcquire())
148+
semaphore.release()
149+
assertEquals(semaphore.availablePermits, 1)
150+
assertTrue(semaphore.tryAcquire())
151+
}
152+
153+
@Test
154+
fun testReleaseAcquiredPermits() = runTest {
155+
val semaphore = Semaphore(5, acquiredPermits = 4)
156+
assertEquals(semaphore.availablePermits, 1)
157+
repeat(4) { semaphore.release() }
158+
assertEquals(5, semaphore.availablePermits)
159+
assertFailsWith<IllegalStateException> { semaphore.release() }
160+
repeat(5) { assertTrue(semaphore.tryAcquire()) }
161+
assertFalse(semaphore.tryAcquire())
162+
}
163+
164+
@Test
165+
fun testIllegalArguments() {
166+
assertFailsWith<IllegalArgumentException> { Semaphore(-1, 0) }
167+
assertFailsWith<IllegalArgumentException> { Semaphore(0, 0) }
168+
assertFailsWith<IllegalArgumentException> { Semaphore(1, -1) }
169+
assertFailsWith<IllegalArgumentException> { Semaphore(1, 2) }
170+
}
143171
}

0 commit comments

Comments
 (0)