|
1 | 1 | package kotlinx.coroutines.sync
|
2 | 2 |
|
3 | 3 | import kotlinx.atomicfu.*
|
4 |
| -import kotlinx.coroutines.CancelHandler |
5 |
| -import kotlinx.coroutines.CancellableContinuation |
6 |
| -import kotlinx.coroutines.asHandler |
| 4 | +import kotlinx.coroutines.* |
7 | 5 | import kotlinx.coroutines.internal.*
|
8 |
| -import kotlinx.coroutines.suspendAtomicCancellableCoroutine |
| 6 | +import kotlinx.coroutines.selects.select |
9 | 7 | import kotlin.coroutines.resume
|
10 | 8 | import kotlin.jvm.JvmField
|
11 | 9 | import kotlin.math.max
|
12 | 10 |
|
| 11 | +/** |
| 12 | + * A counting semaphore for coroutines. It maintains a number of available permits. |
| 13 | + * Each [acquire] suspends if necessary until a permit is available, and then takes it. |
| 14 | + * Each [release] adds a permit, potentially releasing a suspended acquirer. |
| 15 | + * |
| 16 | + * Semaphore with `maxPermits = 1` is essentially a [Mutex]. |
| 17 | + **/ |
13 | 18 | public interface Semaphore {
|
| 19 | + /** |
| 20 | + * Returns the current number of available permits available in this semaphore. |
| 21 | + */ |
14 | 22 | public val availablePermits: Int
|
15 |
| - public fun tryAcquire(): Boolean |
| 23 | + |
| 24 | + /** |
| 25 | + * Acquires a permit from this semaphore, suspending until one is available. |
| 26 | + * All suspending acquirers are processed in first-in-first-out (FIFO) order. |
| 27 | + * |
| 28 | + * This suspending function is cancellable. If the [Job] of the current coroutine is cancelled or completed while this |
| 29 | + * function is suspended, this function immediately resumes with [CancellationException]. |
| 30 | + * |
| 31 | + * *Cancellation of suspended lock invocation is atomic* -- when this function |
| 32 | + * throws [CancellationException] it means that the mutex was not locked. |
| 33 | + * |
| 34 | + * Note, that this function does not check for cancellation when it is not suspended. |
| 35 | + * Use [yield] or [CoroutineScope.isActive] to periodically check for cancellation in tight loops if needed. |
| 36 | + * |
| 37 | + * Use [tryAcquire] to try acquire a permit of this semaphore without suspension. |
| 38 | + */ |
16 | 39 | public suspend fun acquire()
|
| 40 | + |
| 41 | + /** |
| 42 | + * Tries to acquire a permit from this semaphore without suspension. |
| 43 | + * |
| 44 | + * @return `true` if a permit was acquired, `false` otherwise. |
| 45 | + */ |
| 46 | + public fun tryAcquire(): Boolean |
| 47 | + |
| 48 | + /** |
| 49 | + * Releases a permit, returning it into this semaphore. Resumes the first |
| 50 | + * suspending acquirer if there is one at the point of invocation. |
| 51 | + */ |
17 | 52 | public fun release()
|
18 | 53 | }
|
19 | 54 |
|
| 55 | +/** |
| 56 | + * Creates new [Semaphore] instance. |
| 57 | + */ |
| 58 | +@Suppress("FunctionName") |
20 | 59 | public fun Semaphore(maxPermits: Int, acquiredPermits: Int = 0): Semaphore = SemaphoreImpl(maxPermits, acquiredPermits)
|
21 | 60 |
|
| 61 | +/** |
| 62 | + * Executes the given [action] with acquiring a permit from this semaphore at the beginning |
| 63 | + * and releasing it after the [action] is completed. |
| 64 | + * |
| 65 | + * @return the return value of the [action]. |
| 66 | + */ |
22 | 67 | public suspend inline fun <T> Semaphore.withSemaphore(action: () -> T): T {
|
23 | 68 | acquire()
|
24 | 69 | try {
|
|
0 commit comments