# dev.inmo.micro_utils.coroutines

# Package-level declarations

## Types

AccumulatorFlow
Link copied to clipboard
class AccumulatorFlow < T >(sourceDataFlow: Flow< T >, scope: CoroutineScope) : AbstractFlow< T >

This Flow will have behaviour very similar to SharedFlow, but there are several differences:

ActorAction
Link copied to clipboard
interface ActorAction < T >
ContextSafelyExceptionHandler
Link copied to clipboard
class ContextSafelyExceptionHandler (val handler: ExceptionHandler < Unit >) : CoroutineContext.Element

ExceptionHandler wrapper which was created to make possible to use handler across all coroutines calls

ContextSafelyExceptionHandlerKey
Link copied to clipboard
object ContextSafelyExceptionHandlerKey : CoroutineContext.Key < ContextSafelyExceptionHandler >

This key can (and will) be used to get ContextSafelyExceptionHandler from coroutineContext of suspend functions and in ContextSafelyExceptionHandler for defining of its CoroutineContext.Element.key

DeferredAction
Link copied to clipboard
class DeferredAction < T , O >(val deferred: Deferred< T >, val callback: suspend ( T ) -> O )
DoWithFirstBuilder
Link copied to clipboard
class DoWithFirstBuilder < T >(scope: CoroutineScope)
ExceptionHandler
Link copied to clipboard
typealias ExceptionHandler < T > = suspend ( Throwable ) -> T
FlowOnHierarchyChangeListener
Link copied to clipboard
class FlowOnHierarchyChangeListener (recursive: Boolean = false, _onChildViewAdded: MutableSharedFlow< Pair < View , View >> = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE), _onChildViewRemoved: MutableSharedFlow< Pair < View , View >> = MutableSharedFlow(extraBufferCapacity = Int.MAX_VALUE)) : ViewGroup.OnHierarchyChangeListener

kotlinx.coroutines.flow.Flow-based android.view.ViewGroup.OnHierarchyChangeListener

SmartMutex
Link copied to clipboard
sealed interface SmartMutex

It is interface which will work like classic Mutex, but in difference have lockStateFlow for listening of the SmartMutex state.

SmartRWLocker
Link copied to clipboard
class SmartRWLocker (readPermits: Int = Int.MAX_VALUE, writeIsLocked: Boolean = false)

Composite mutex which works with next rules:

SmartSemaphore
Link copied to clipboard
sealed interface SmartSemaphore

It is interface which will work like classic Semaphore, but in difference have permitsStateFlow for listening of the SmartSemaphore state.

SpecialMutableStateFlow
Link copied to clipboard
open class SpecialMutableStateFlow < T >(initialValue: T ) : MutableStateFlow< T > , FlowCollector< T > , MutableSharedFlow< T >

Works like StateFlow, but guarantee that latest value update will always be delivered to each active subscriber

## Properties

asDeferred
Link copied to clipboard
val < T > T . asDeferred : Deferred< T >
Default
Link copied to clipboard
val Default : CoroutineDispatcher
defaultSafelyExceptionHandler
Link copied to clipboard
var defaultSafelyExceptionHandler : ExceptionHandler < Nothing >

This instance will be used in all calls of safely where exception handler has not been passed

defaultSafelyWithoutExceptionHandler
Link copied to clipboard
var defaultSafelyWithoutExceptionHandler : ExceptionHandler < Unit >

This instance will be used in all calls of safelyWithoutExceptions as an exception handler for safely call

defaultSafelyWithoutExceptionHandlerWithNull
Link copied to clipboard
val defaultSafelyWithoutExceptionHandlerWithNull : ExceptionHandler < Nothing ?>

Use this handler in cases you wish to include handling of exceptions by defaultSafelyWithoutExceptionHandler and returning null at one time

IO
Link copied to clipboard
val IO : CoroutineDispatcher
UI
Link copied to clipboard
val UI : MainCoroutineDispatcher

## Functions

accumulatorFlow
Link copied to clipboard
fun < T > Channel< T >. accumulatorFlow (scope: CoroutineScope): Flow< T >

Creates AccumulatorFlow using this with receiveAsFlow to get

fun < T > Flow< T >. accumulatorFlow (scope: CoroutineScope): Flow< T >

Creates AccumulatorFlow using this as base Flow

actor
Link copied to clipboard
fun < T > CoroutineScope. actor (channelCapacity: Int = Channel.UNLIMITED, block: suspend ( T ) -> Unit ): Channel< T >
actorAsync
Link copied to clipboard
fun < T > CoroutineScope. actorAsync (channelCapacity: Int = Channel.UNLIMITED, markerFactory: suspend ( T ) -> Any ? = { null }, block: suspend ( T ) -> Unit ): Channel< T >
asyncSafely
Link copied to clipboard
fun < T > CoroutineScope. asyncSafely (context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, onException: ExceptionHandler < T > = defaultSafelyExceptionHandler, block: suspend CoroutineScope.() -> T ): Deferred< Result < T >>
asyncSafelyWithoutExceptions
Link copied to clipboard
fun < T > CoroutineScope. asyncSafelyWithoutExceptions (context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, onException: ExceptionHandler < T ?> = defaultSafelyWithoutExceptionHandlerWithNull, block: suspend CoroutineScope.() -> T ): Deferred< Result < T ?>>
asyncWeak
Link copied to clipboard
fun < T > CoroutineScope. asyncWeak (context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> T ): Deferred< T >

this will be used as base for WeakScope. Other parameters (context, start, block) will be used to create async

awaitFirst
Link copied to clipboard
suspend fun < T > awaitFirst (vararg deferreds: Deferred< T >, cancelOthers: Boolean = true): T

Trying to Deferred.await on all deferreds. The first Deferred completed its work will interrupt all others awaits and, if cancelOthers passed as true (by default), will also cancel all the others deferreds

suspend fun < T > awaitFirst (vararg deferreds: Deferred< T >, scope: CoroutineScope, cancelOnResult: Boolean = true): T

Trying to Deferred.await on all deferreds. The first Deferred completed its work will interrupt all others awaits and, if cancelOnResult passed as true (by default), will also cancel all the others deferreds

awaitFirst
Link copied to clipboard
suspend fun < T > Iterable <Deferred< T >>. awaitFirst (cancelOthers: Boolean = true): T

Trying to Deferred.await on all thiss. The first Deferred completed its work will interrupt all others awaits and, if cancelOthers passed as true (by default), will also cancel all the others Deferreds

suspend fun < T > Iterable <Deferred< T >>. awaitFirst (scope: CoroutineScope, cancelOnResult: Boolean = true): T

Trying to Deferred.await on all thiss. The first Deferred completed its work will interrupt all others awaits and, if cancelOnResult passed as true (by default), will also cancel all the others Deferreds

awaitFirstWithDeferred
Link copied to clipboard
suspend fun < T > Iterable <Deferred< T >>. awaitFirstWithDeferred (scope: CoroutineScope, cancelOnResult: Boolean = true): Pair <Deferred< T >, T >

Trying to Deferred.await on all thiss. The first Deferred completed its work will interrupt all others awaits and, if cancelOnResult passed as true (by default), will also cancel all the others Deferreds

buildAction
Link copied to clipboard
fun < T , O > Deferred< T >. buildAction (callback: suspend ( T ) -> O ): DeferredAction < T , O >
contextSafelyExceptionHandler
Link copied to clipboard
suspend fun contextSafelyExceptionHandler (): ContextSafelyExceptionHandler ?
CoroutineScopeWithDefaultFallback
Link copied to clipboard
fun CoroutineScopeWithDefaultFallback (context: CoroutineContext , defaultExceptionsHandler: ExceptionHandler < Unit >): CoroutineScope
createActionsActor
Link copied to clipboard
fun CoroutineScope. createActionsActor (): Channel<suspend () -> Unit >

Planned to use with doWithSuspending. Will execute incoming lambdas sequentially

createSafeActionsActor
Link copied to clipboard
inline fun CoroutineScope. createSafeActionsActor (noinline onException: ExceptionHandler < Unit > = defaultSafelyExceptionHandler): Channel<suspend () -> Unit >

Planned to use with doWithSuspending. Will execute incoming lambdas sequentially

debouncedBy
Link copied to clipboard
fun < T > Flow< T >. debouncedBy (timeout: ( T ) -> Long , markerFactory: ( T ) -> Any ?): Flow< T >
fun < T > Flow< T >. debouncedBy (timeout: Long , markerFactory: ( T ) -> Any ?): Flow< T >
fun < T > Flow< T >. debouncedBy (timeout: Duration , markerFactory: ( T ) -> Any ?): Flow< T >
doIn
Link copied to clipboard
inline suspend fun < T > doIn (context: CoroutineContext , noinline block: suspend CoroutineScope.() -> T ): T
doInDefault
Link copied to clipboard
inline suspend fun < T > doInDefault (noinline block: suspend CoroutineScope.() -> T ): T
doInIO
Link copied to clipboard
inline suspend fun < T > doInIO (noinline block: suspend CoroutineScope.() -> T ): T
doInUI
Link copied to clipboard
inline suspend fun < T > doInUI (noinline block: suspend CoroutineScope.() -> T ): T
doOutsideOfCoroutine
Link copied to clipboard
suspend fun < T > doOutsideOfCoroutine (block: () -> T ): T

Call this method in case you need to do something in common thread (like reading of file in JVM)

doSynchronously
Link copied to clipboard
fun < T > doSynchronously (block: suspend CoroutineScope.() -> T ): T
doSynchronously
Link copied to clipboard
fun < T > CoroutineScope. doSynchronously (block: suspend CoroutineScope.() -> T ): T
doWithSuspending
Link copied to clipboard
suspend fun < T > Channel<suspend () -> Unit >. doWithSuspending (action: ActorAction < T >): T

Must be use with actor created by createActionsActor or createSafeActionsActor. Will send lambda which will execute action and return result.

filterNotNull
Link copied to clipboard
fun < T > Flow< T >. filterNotNull (): Flow< T & Any >
first
Link copied to clipboard
suspend fun < T > List <Deferred< T >>. first (scope: CoroutineScope, cancelOnResult: Boolean = true): T
firstNotNull
Link copied to clipboard
suspend fun < T > Flow< T ?>. firstNotNull (): T
firstOf
Link copied to clipboard
suspend fun < T > CoroutineScope. firstOf (vararg variants: Deferred< T >, cancelOnResult: Boolean = true): T
suspend fun < T > CoroutineScope. firstOf (cancelOnResult: Boolean = true, block: DoWithFirstBuilder < T >.() -> Unit ): T
suspend fun < T > CoroutineScope. firstOf (variants: Iterable <Deferred< T >>, cancelOnResult: Boolean = true): T
flatMap
Link copied to clipboard
@ JvmName (name = "flatMapIterable")
inline fun < T , R > Flow< Iterable < T >>. flatMap (crossinline mapper: suspend ( T ) -> R ): Flow< R >
inline fun < T , R > Flow<Flow< T >>. flatMap (crossinline mapper: suspend ( T ) -> R ): Flow< R >
flatMapNotNull
Link copied to clipboard
@ JvmName (name = "flatMapNotNullIterable")
inline fun < T , R > Flow< Iterable < T >>. flatMapNotNull (crossinline mapper: suspend ( T ) -> R ): Flow< R & Any >
inline fun < T , R > Flow<Flow< T >>. flatMapNotNull (crossinline mapper: suspend ( T ) -> R ): Flow< R & Any >
flatten
Link copied to clipboard
@ JvmName (name = "flattenIterable")
fun < T > Flow< Iterable < T >>. flatten (): Flow< T >
fun < T > Flow<Flow< T >>. flatten (): Flow< T >
invoke
Link copied to clipboard
inline suspend operator fun < T > FlowCollector< T >. invoke (value: T )
invokeFirstOf
Link copied to clipboard
suspend fun < O > invokeFirstOf (scope: CoroutineScope, vararg variants: DeferredAction <*, O >, cancelOnResult: Boolean = true): O
invokeFirstOf
Link copied to clipboard
suspend fun < O > Iterable < DeferredAction <*, O >>. invokeFirstOf (scope: CoroutineScope, cancelOnResult: Boolean = true): O
invokeOnFirst
Link copied to clipboard
suspend fun < T , O > invokeOnFirst (scope: CoroutineScope, vararg variants: Deferred< T >, cancelOnResult: Boolean = true, callback: suspend ( T ) -> O ): O
invokeOnFirst
Link copied to clipboard
suspend fun < T , O > Iterable <Deferred< T >>. invokeOnFirst (scope: CoroutineScope, cancelOnResult: Boolean = true, callback: suspend ( T ) -> O ): O
invokeOnFirstOf
Link copied to clipboard
suspend fun < T , O > CoroutineScope. invokeOnFirstOf (cancelOnResult: Boolean = true, block: DoWithFirstBuilder < T >.() -> Unit , callback: suspend ( T ) -> O ): O
joinFirst
Link copied to clipboard
suspend fun joinFirst (vararg jobs: Job, cancelOthers: Boolean = true): Job
suspend fun joinFirst (vararg jobs: Job, scope: CoroutineScope, cancelOthers: Boolean = true): Job

Trying to Job.join on all jobs. The first Job completed its work will interrupt all others joins and, if cancelOthers passed as true (by default), will also cancel all the others Jobs

joinFirst
Link copied to clipboard
suspend fun Iterable <Job>. joinFirst (cancelOthers: Boolean = true): Job
suspend fun Iterable <Job>. joinFirst (scope: CoroutineScope, cancelOthers: Boolean = true): Job

Trying to Job.join on all thiss. The first Job completed its work will interrupt all others joins and, if cancelOthers passed as true (by default), will also cancel all the others Jobs

launchInCurrentThread
Link copied to clipboard
fun < T > launchInCurrentThread (block: suspend CoroutineScope.() -> T ): T
launchSafely
Link copied to clipboard
fun CoroutineScope. launchSafely (context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, onException: ExceptionHandler < Unit > = defaultSafelyExceptionHandler, block: suspend CoroutineScope.() -> Unit ): Job
launchSafelyWithoutExceptions
Link copied to clipboard
fun CoroutineScope. launchSafelyWithoutExceptions (context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, onException: ExceptionHandler < Unit ?> = defaultSafelyWithoutExceptionHandlerWithNull, block: suspend CoroutineScope.() -> Unit ): Job
launchSynchronously
Link copied to clipboard
fun < T > launchSynchronously (block: suspend CoroutineScope.() -> T ): T
launchSynchronously
Link copied to clipboard
fun < T > CoroutineScope. launchSynchronously (block: suspend CoroutineScope.() -> T ): T
launchWeak
Link copied to clipboard
fun CoroutineScope. launchWeak (context: CoroutineContext = EmptyCoroutineContext, start: CoroutineStart = CoroutineStart.DEFAULT, block: suspend CoroutineScope.() -> Unit ): Job

this will be used as base for WeakScope. Other parameters (context, start, block) will be used to launch

LinkedSupervisorJob
Link copied to clipboard
fun CoroutineContext . LinkedSupervisorJob (additionalContext: CoroutineContext ? = null): CoroutineContext
fun CoroutineScope. LinkedSupervisorJob (additionalContext: CoroutineContext ? = null): CoroutineContext
LinkedSupervisorScope
Link copied to clipboard
fun CoroutineContext . LinkedSupervisorScope (additionalContext: CoroutineContext ? = null): CoroutineScope
fun CoroutineScope. LinkedSupervisorScope (additionalContext: CoroutineContext ? = null): CoroutineScope
plus
Link copied to clipboard
inline operator fun < T > Flow< T >. plus (other: Flow< T >): Flow< T >
preloadImage
Link copied to clipboard
suspend fun preloadImage (src: String ): Image
runCatchingSafely
Link copied to clipboard
inline suspend fun < T > runCatchingSafely (block: suspend () -> T ): Result < T >

Launching runCatchingSafely with defaultSafelyExceptionHandler as `onException` parameter

inline suspend fun < T > runCatchingSafely (onException: ExceptionHandler < T >, block: suspend () -> T ): Result < T >

Launching block in runCatching. In case of failure, it will:

runCatchingSafely
Link copied to clipboard
inline suspend fun < T , R > R . runCatchingSafely (block: suspend R .() -> T ): Result < T >
inline suspend fun < T , R > R . runCatchingSafely (onException: ExceptionHandler < T >, block: suspend R .() -> T ): Result < T >
runCatchingSafelyWithoutExceptions
Link copied to clipboard
suspend fun < T > runCatchingSafelyWithoutExceptions (onException: ExceptionHandler < T ?> = defaultSafelyExceptionHandler, block: suspend () -> T ): Result < T ?>
safeActor
Link copied to clipboard
inline fun < T > CoroutineScope. safeActor (channelCapacity: Int = Channel.UNLIMITED, noinline onException: ExceptionHandler < Unit > = defaultSafelyExceptionHandler, crossinline block: suspend ( T ) -> Unit ): Channel< T >
safeActorAsync
Link copied to clipboard
inline fun < T > CoroutineScope. safeActorAsync (channelCapacity: Int = Channel.UNLIMITED, noinline onException: ExceptionHandler < Unit > = defaultSafelyExceptionHandler, noinline markerFactory: suspend ( T ) -> Any ? = { null }, crossinline block: suspend ( T ) -> Unit ): Channel< T >
safely
Link copied to clipboard
inline suspend fun < T > safely (block: suspend () -> T ): T

Calls safely with passing of defaultSafelyExceptionHandler as `onException`

inline suspend fun < T > safely (onException: ExceptionHandler < T >, block: suspend () -> T ): T

Calls runCatchingSafely and getting the result via Result.getOrThrow

safely
Link copied to clipboard
inline suspend fun < T , R > R . safely (block: suspend R .() -> T ): T
safelyWithContextExceptionHandler
Link copied to clipboard
suspend fun < T > safelyWithContextExceptionHandler (contextExceptionHandler: ExceptionHandler < Unit >, safelyExceptionHandler: ExceptionHandler < T > = defaultSafelyExceptionHandler, block: suspend () -> T ): T

This method will set new coroutineContext with ContextSafelyExceptionHandler. In case if coroutineContext already contains ContextSafelyExceptionHandler, ContextSafelyExceptionHandler.handler will be used BEFORE contextExceptionHandler in case of exception.

safelyWithoutExceptions
Link copied to clipboard
suspend fun < T > safelyWithoutExceptions (onException: ExceptionHandler < T > = defaultSafelyExceptionHandler, block: suspend () -> T ): T ?

Shortcut for safely with exception handler, that as expected must return null in case of impossible creating of result from exception (instead of throwing it, by default always returns null)

selectFileOrNull
Link copied to clipboard
suspend fun selectFileOrNull (inputSetup: ( HTMLInputElement ) -> Unit = {}, onFailure: ( Throwable ) -> Unit = {}): MPPFile ?
selectFileOrThrow
Link copied to clipboard
suspend fun selectFileOrThrow (inputSetup: ( HTMLInputElement ) -> Unit = {}): MPPFile
setOnHierarchyChangeListenerRecursively
Link copied to clipboard
fun ViewGroup . setOnHierarchyChangeListenerRecursively (listener: ViewGroup.OnHierarchyChangeListener )

Use ViewGroup.setOnHierarchyChangeListener recursively for all available ViewGroups starting with this. This extension DO NOT guarantee that recursive subscription will happen after this method call

subscribe
Link copied to clipboard
inline fun < T > Flow< T >. subscribe (scope: CoroutineScope, noinline block: suspend ( T ) -> Unit ): Job

Shortcut for chain if Flow.onEach and Flow.launchIn

subscribeAsync
Link copied to clipboard
fun < T , M > Flow< T >. subscribeAsync (scope: CoroutineScope, markerFactory: suspend ( T ) -> M , block: suspend ( T ) -> Unit ): Job
subscribeSafely
Link copied to clipboard
inline fun < T > Flow< T >. subscribeSafely (scope: CoroutineScope, noinline onException: ExceptionHandler < Unit > = defaultSafelyExceptionHandler, noinline block: suspend ( T ) -> Unit ): Job

Use subscribe, but all blocks will be called inside of safely function. Use onException to set up your reaction for Throwables

subscribeSafelyAsync
Link copied to clipboard
fun < T , M > Flow< T >. subscribeSafelyAsync (scope: CoroutineScope, markerFactory: suspend ( T ) -> M , onException: ExceptionHandler < Unit > = defaultSafelyExceptionHandler, block: suspend ( T ) -> Unit ): Job
subscribeSafelySkippingExceptions
Link copied to clipboard
inline fun < T > Flow< T >. subscribeSafelySkippingExceptions (scope: CoroutineScope, noinline block: suspend ( T ) -> Unit ): Job

Use subscribeSafelyWithoutExceptions, but all exceptions inside of safely will be skipped

subscribeSafelySkippingExceptionsAsync
Link copied to clipboard
fun < T , M > Flow< T >. subscribeSafelySkippingExceptionsAsync (scope: CoroutineScope, markerFactory: suspend ( T ) -> M , block: suspend ( T ) -> Unit ): Job
subscribeSafelyWithoutExceptions
Link copied to clipboard
inline fun < T > Flow< T >. subscribeSafelyWithoutExceptions (scope: CoroutineScope, noinline onException: ExceptionHandler < T ?> = defaultSafelyWithoutExceptionHandlerWithNull, noinline block: suspend ( T ) -> Unit ): Job

Use subscribeSafelyWithoutExceptions, but all exceptions will be passed to defaultSafelyExceptionHandler

subscribeSafelyWithoutExceptionsAsync
Link copied to clipboard
fun < T , M > Flow< T >. subscribeSafelyWithoutExceptionsAsync (scope: CoroutineScope, markerFactory: suspend ( T ) -> M , onException: ExceptionHandler < T ?> = defaultSafelyWithoutExceptionHandlerWithNull, block: suspend ( T ) -> Unit ): Job
takeNotNull
Link copied to clipboard
fun < T > Flow< T >. takeNotNull (): Flow< T & Any >
toByteArray
Link copied to clipboard
suspend fun Blob . toByteArray (): ByteArray
visibilityFlow
Link copied to clipboard
fun Element . visibilityFlow (): Flow< Boolean >
waitReadRelease
Link copied to clipboard
suspend fun SmartRWLocker . waitReadRelease (permits: Int = 1): Int

Will wait until the SmartSemaphore.permitsStateFlow of this instance will have permits count free permits.

waitRelease
Link copied to clipboard
suspend fun SmartSemaphore . waitRelease (permits: Int = 1): Int

Will wait until the SmartSemaphore.permitsStateFlow of this instance will have permits count free permits.

waitUnlock
Link copied to clipboard
suspend fun SmartMutex . waitUnlock (): Boolean

Will wait until the SmartMutex.lockStateFlow of this instance will be false.

waitWriteUnlock
Link copied to clipboard
suspend fun SmartRWLocker . waitWriteUnlock (): Boolean

Will wait until the SmartMutex.lockStateFlow of this instance will be false.

WeakScope
Link copied to clipboard
fun WeakScope (context: CoroutineContext ): CoroutineScope

Created CoroutineScope which will launch listening of context job completing and drop itself. Current weak scope will not be attached to context directly. So, this CoroutineScope will not prevent parent one from cancelling if it is launched with supervisorScope or coroutineScope, but still will follow closing status of parent Job

fun WeakScope (scope: CoroutineScope): CoroutineScope

Created CoroutineScope which will launch listening of scope job completing and drop itself. Current weak scope will not be attached to scope directly. So, this CoroutineScope will not prevent parent one from cancelling if it is launched with supervisorScope or coroutineScope, but still will follow closing status of parent Job

withAcquire
Link copied to clipboard
inline suspend fun < T > SmartSemaphore.Mutable . withAcquire (permits: Int = 1, action: () -> T ): T

Will call SmartSemaphore.Mutable.lock, then execute action and return the result after SmartSemaphore.Mutable.unlock

withLock
Link copied to clipboard
inline suspend fun < T > SmartMutex.Mutable . withLock (action: () -> T ): T

Will call SmartMutex.Mutable.lock, then execute action and return the result after SmartMutex.Mutable.unlock

withReadAcquire
Link copied to clipboard
inline suspend fun < T > SmartRWLocker . withReadAcquire (action: () -> T ): T

Will call SmartSemaphore.Mutable.lock, then execute action and return the result after SmartSemaphore.Mutable.unlock

withWriteLock
Link copied to clipboard
inline suspend fun < T > SmartRWLocker . withWriteLock (action: () -> T ): T

Will call SmartMutex.Mutable.lock, then execute action and return the result after SmartMutex.Mutable.unlock