Skip to content

Clarify thread-safety of SharedFlow methods in docs #2399

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 2 commits into from
Nov 18, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions kotlinx-coroutines-core/api/kotlinx-coroutines-core.api
Original file line number Diff line number Diff line change
Expand Up @@ -1064,6 +1064,7 @@ public final class kotlinx/coroutines/flow/LintKt {
}

public abstract interface class kotlinx/coroutines/flow/MutableSharedFlow : kotlinx/coroutines/flow/FlowCollector, kotlinx/coroutines/flow/SharedFlow {
public abstract fun emit (Ljava/lang/Object;Lkotlin/coroutines/Continuation;)Ljava/lang/Object;
public abstract fun getSubscriptionCount ()Lkotlinx/coroutines/flow/StateFlow;
public abstract fun resetReplayCache ()V
public abstract fun tryEmit (Ljava/lang/Object;)Z
Expand Down
17 changes: 17 additions & 0 deletions kotlinx-coroutines-core/common/src/flow/SharedFlow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,17 @@ public interface SharedFlow<out T> : Flow<T> {
* Use the `MutableSharedFlow(...)` constructor function to create an implementation.
*/
public interface MutableSharedFlow<T> : SharedFlow<T>, FlowCollector<T> {
/**
* Emits a [value] to this shared flow, suspending on buffer overflow if the shared flow was created
* with the default [BufferOverflow.SUSPEND] strategy.
*
* See [tryEmit] for a non-suspending variant of this function.
*
* This method is **thread-safe** and can be safely invoked from concurrent coroutines without
* external synchronization.
*/
override suspend fun emit(value: T)

/**
* Tries to emit a [value] to this shared flow without suspending. It returns `true` if the value was
* emitted successfully. When this function returns `false`, it means that the call to a plain [emit]
Expand All @@ -155,6 +166,9 @@ public interface MutableSharedFlow<T> : SharedFlow<T>, FlowCollector<T> {
* A shared flow configured with a [BufferOverflow] strategy other than [SUSPEND][BufferOverflow.SUSPEND]
* (either [DROP_OLDEST][BufferOverflow.DROP_OLDEST] or [DROP_LATEST][BufferOverflow.DROP_LATEST]) never
* suspends on [emit], and thus `tryEmit` to such a shared flow always returns `true`.
*
* This method is **thread-safe** and can be safely invoked from concurrent coroutines without
* external synchronization.
*/
public fun tryEmit(value: T): Boolean

Expand Down Expand Up @@ -190,6 +204,9 @@ public interface MutableSharedFlow<T> : SharedFlow<T>, FlowCollector<T> {
* supported, and throws an [UnsupportedOperationException]. To reset a [MutableStateFlow]
* to an initial value, just update its [value][MutableStateFlow.value].
*
* This method is **thread-safe** and can be safely invoked from concurrent coroutines without
* external synchronization.
*
* **Note: This is an experimental api.** This function may be removed or renamed in the future.
*/
@ExperimentalCoroutinesApi
Expand Down
6 changes: 6 additions & 0 deletions kotlinx-coroutines-core/common/src/flow/StateFlow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,9 @@ public interface MutableStateFlow<T> : StateFlow<T>, MutableSharedFlow<T> {
* The current value of this state flow.
*
* Setting a value that is [equal][Any.equals] to the previous one does nothing.
*
* This property is **thread-safe** and can be safely updated from concurrent coroutines without
* external synchronization.
*/
public override var value: T

Expand All @@ -170,6 +173,9 @@ public interface MutableStateFlow<T> : StateFlow<T>, MutableSharedFlow<T> {
* This function use a regular comparison using [Any.equals]. If both [expect] and [update] are equal to the
* current [value], this function returns `true`, but it does not actually change the reference that is
* stored in the [value].
*
* This method is **thread-safe** and can be safely invoked from concurrent coroutines without
* external synchronization.
*/
public fun compareAndSet(expect: T, update: T): Boolean
}
Expand Down