-
Notifications
You must be signed in to change notification settings - Fork 70
Mutex for Kotlin/Common #508
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
bd7b050
Introduce mutex
bbrockbernd 2ca81db
Minor improvements
bbrockbernd d01638b
Revert lincheck version
bbrockbernd 50b57bf
Fix inconsistent package defs
bbrockbernd 59acf29
Lazy init native mutex in lincheck tests
bbrockbernd 2ec167a
Add comment
bbrockbernd 72e4a43
Exclude lincheck tests from the `transformed` test jobs
bbrockbernd 79acfb0
Fixed node not being dequed properly after timeout. Also added valida…
bbrockbernd 44ca9de
Fix jsAndWasm comments, remove redundant return, apply terminology su…
bbrockbernd 072099f
Turn redundant ifs into checks, assert for native is still experimental.
bbrockbernd 8bd65f9
Exclude all tests from transformation that end with "LincheckTest"
bbrockbernd 94e82d5
Bugfix mutex
bbrockbernd 2f09419
Remove volatiles
bbrockbernd 6bb6db5
Use check(){} api
bbrockbernd af4a73b
Apply suggestions
bbrockbernd 9b56875
Remove LockIntTest class
bbrockbernd 35427d0
Refactor nativemutextest
bbrockbernd b0fc370
Moved lincheck dependency to toml file.
bbrockbernd dfb6ea0
Updated comment according to suggestion
bbrockbernd c653f27
Update lincheck to latest
bbrockbernd File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -45,6 +45,15 @@ final class <#A: kotlin/Any?> kotlinx.atomicfu/AtomicRef { // kotlinx.atomicfu/A | |
final fun compareAndSet(#A, #A): kotlin/Boolean // kotlinx.atomicfu/AtomicRef.compareAndSet|compareAndSet(1:0;1:0){}[0] | ||
} | ||
|
||
final class kotlinx.atomicfu.locks/SynchronousMutex { // kotlinx.atomicfu.locks/SynchronousMutex|null[0] | ||
constructor <init>() // kotlinx.atomicfu.locks/SynchronousMutex.<init>|<init>(){}[0] | ||
|
||
final fun lock() // kotlinx.atomicfu.locks/SynchronousMutex.lock|lock(){}[0] | ||
final fun tryLock(): kotlin/Boolean // kotlinx.atomicfu.locks/SynchronousMutex.tryLock|tryLock(){}[0] | ||
final fun tryLock(kotlin.time/Duration): kotlin/Boolean // kotlinx.atomicfu.locks/SynchronousMutex.tryLock|tryLock(kotlin.time.Duration){}[0] | ||
final fun unlock() // kotlinx.atomicfu.locks/SynchronousMutex.unlock|unlock(){}[0] | ||
} | ||
|
||
final class kotlinx.atomicfu/AtomicBoolean { // kotlinx.atomicfu/AtomicBoolean|null[0] | ||
final var value // kotlinx.atomicfu/AtomicBoolean.value|{}value[0] | ||
// Targets: [native] | ||
|
@@ -278,6 +287,7 @@ final inline fun (kotlinx.atomicfu/AtomicLong).kotlinx.atomicfu/getAndUpdate(kot | |
final inline fun (kotlinx.atomicfu/AtomicLong).kotlinx.atomicfu/loop(kotlin/Function1<kotlin/Long, kotlin/Unit>): kotlin/Nothing // kotlinx.atomicfu/loop|[email protected](kotlin.Function1<kotlin.Long,kotlin.Unit>){}[0] | ||
final inline fun (kotlinx.atomicfu/AtomicLong).kotlinx.atomicfu/update(kotlin/Function1<kotlin/Long, kotlin/Long>) // kotlinx.atomicfu/update|[email protected](kotlin.Function1<kotlin.Long,kotlin.Long>){}[0] | ||
final inline fun (kotlinx.atomicfu/AtomicLong).kotlinx.atomicfu/updateAndGet(kotlin/Function1<kotlin/Long, kotlin/Long>): kotlin/Long // kotlinx.atomicfu/updateAndGet|[email protected](kotlin.Function1<kotlin.Long,kotlin.Long>){}[0] | ||
final inline fun <#A: kotlin/Any?> (kotlinx.atomicfu.locks/SynchronousMutex).kotlinx.atomicfu.locks/withLock(kotlin/Function0<#A>): #A // kotlinx.atomicfu.locks/withLock|[email protected](kotlin.Function0<0:0>){0§<kotlin.Any?>}[0] | ||
final inline fun <#A: kotlin/Any?> (kotlinx.atomicfu/AtomicRef<#A>).kotlinx.atomicfu/getAndUpdate(kotlin/Function1<#A, #A>): #A // kotlinx.atomicfu/getAndUpdate|[email protected]<0:0>(kotlin.Function1<0:0,0:0>){0§<kotlin.Any?>}[0] | ||
final inline fun <#A: kotlin/Any?> (kotlinx.atomicfu/AtomicRef<#A>).kotlinx.atomicfu/loop(kotlin/Function1<#A, kotlin/Unit>): kotlin/Nothing // kotlinx.atomicfu/loop|[email protected]<0:0>(kotlin.Function1<0:0,kotlin.Unit>){0§<kotlin.Any?>}[0] | ||
final inline fun <#A: kotlin/Any?> (kotlinx.atomicfu/AtomicRef<#A>).kotlinx.atomicfu/update(kotlin/Function1<#A, #A>) // kotlinx.atomicfu/update|[email protected]<0:0>(kotlin.Function1<0:0,0:0>){0§<kotlin.Any?>}[0] | ||
|
@@ -297,14 +307,6 @@ open annotation class kotlinx.atomicfu.locks/ExperimentalThreadBlockingApi : kot | |
constructor <init>() // kotlinx.atomicfu.locks/ExperimentalThreadBlockingApi.<init>|<init>(){}[0] | ||
} | ||
|
||
// Targets: [native] | ||
final class kotlinx.atomicfu.locks/NativeMutexNode { // kotlinx.atomicfu.locks/NativeMutexNode|null[0] | ||
constructor <init>() // kotlinx.atomicfu.locks/NativeMutexNode.<init>|<init>(){}[0] | ||
|
||
final fun lock() // kotlinx.atomicfu.locks/NativeMutexNode.lock|lock(){}[0] | ||
final fun unlock() // kotlinx.atomicfu.locks/NativeMutexNode.unlock|unlock(){}[0] | ||
} | ||
|
||
// Targets: [native] | ||
final class kotlinx.atomicfu.locks/ParkingHandle // kotlinx.atomicfu.locks/ParkingHandle|null[0] | ||
|
||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
57 changes: 0 additions & 57 deletions
57
atomicfu/src/androidNativeMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt
This file was deleted.
Oops, something went wrong.
112 changes: 0 additions & 112 deletions
112
atomicfu/src/appleMain/kotlin/kotlinx/atomicfu/locks/NativeMutexNode.kt
This file was deleted.
Oops, something went wrong.
10 changes: 0 additions & 10 deletions
10
atomicfu/src/appleMain/kotlin/kotlinx/atomicfu/locks/ThreadId.kt
This file was deleted.
Oops, something went wrong.
89 changes: 89 additions & 0 deletions
89
atomicfu/src/commonMain/kotlin/kotlinx/atomicfu/locks/SynchronousMutex.kt
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
package kotlinx.atomicfu.locks | ||
|
||
import kotlin.contracts.ExperimentalContracts | ||
import kotlin.contracts.InvocationKind | ||
import kotlin.contracts.contract | ||
import kotlin.time.Duration | ||
|
||
/** | ||
* Mutual exclusion for Kotlin Multiplatform. | ||
* | ||
* It can protect a shared resource or critical section from multiple thread accesses. | ||
* Threads can acquire the lock by calling [lock] and release the lock by calling [unlock]. | ||
* | ||
* When a thread calls [lock] while another thread is locked, it will suspend until the lock is released. | ||
bbrockbernd marked this conversation as resolved.
Show resolved
Hide resolved
|
||
* When multiple threads are waiting for the lock, they will acquire it in a fair order (first in first out). | ||
* On JVM, a [lock] call can skip the queue if it happens in between a thread releasing and the first in queue acquiring. | ||
* | ||
* It is reentrant, meaning the lock holding thread can call [lock] multiple times without suspending. | ||
* To release the lock (after multiple [lock] calls) an equal number of [unlock] calls are required. | ||
* | ||
* This Mutex should not be used in combination with coroutines and `suspend` functions | ||
* as it blocks the waiting thread. | ||
* Use the `Mutex` from the coroutines library instead. | ||
* | ||
* ```Kotlin | ||
* mutex.withLock { | ||
* // Critical section only executed by | ||
* // one thread at a time. | ||
* } | ||
* ``` | ||
*/ | ||
public expect class SynchronousMutex() { | ||
/** | ||
* Tries to lock this mutex, returning `false` if this mutex is already locked. | ||
* | ||
* It is recommended to use [withLock] for safety reasons, so that the acquired lock is always | ||
* released at the end of your critical section, and [unlock] is never invoked before a successful | ||
* lock acquisition. | ||
* | ||
* (JVM only) this call can potentially skip line. | ||
*/ | ||
public fun tryLock(): Boolean | ||
|
||
/** | ||
* Tries to lock this mutex within the given [timeout] period, | ||
* returning `false` if the duration passed without locking. | ||
* | ||
* Note: when [tryLock] succeeds the lock needs to be released by [unlock]. | ||
* When [tryLock] does not succeed the lock does not have to be released. | ||
* | ||
* (JVM only) throws Interrupted exception when thread is interrupted while waiting for lock. | ||
*/ | ||
public fun tryLock(timeout: Duration): Boolean | ||
|
||
/** | ||
* Locks the mutex, blocks the thread until the lock is acquired. | ||
* | ||
* It is recommended to use [withLock] for safety reasons, so that the acquired lock is always | ||
* released at the end of your critical section, and [unlock] is never invoked before a successful | ||
* lock acquisition. | ||
*/ | ||
public fun lock() | ||
|
||
/** | ||
* Releases the lock. | ||
* Throws [IllegalStateException] when the current thread is not holding the lock. | ||
* | ||
* It is recommended to use [withLock] for safety reasons, so that the acquired lock is always | ||
* released at the end of the critical section, and [unlock] is never invoked before a successful | ||
* lock acquisition. | ||
*/ | ||
public fun unlock() | ||
} | ||
|
||
/** | ||
* Executes the given code [block] under this mutex's lock. | ||
* | ||
* @return result of [block] | ||
*/ | ||
@OptIn(ExperimentalContracts::class) | ||
public inline fun <T> SynchronousMutex.withLock(block: () -> T): T { | ||
contract { callsInPlace(block, InvocationKind.EXACTLY_ONCE) } | ||
lock() | ||
return try { | ||
block() | ||
} finally { | ||
unlock() | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I assume removing this implementation detail is safe, but cc @fzhinkin: he probably knows if this was already used by someone else.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, there's a lot of API entries that were unintentionally left public.
Last time I checked, nobody actually use them, but it might be worth explicitly announcing the removal prior the release.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fzhinkin Do you mean deprecating these functions?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. Or posting a message in kotlinlang slack, to bring some attention. Anyway, I'll handle it, don't worry about it.