mirror of
				https://github.com/InsanusMokrassar/MicroUtils.git
				synced 2025-11-04 06:00:22 +00:00 
			
		
		
		
	Compare commits
	
		
			7 Commits
		
	
	
		
			revert-245
			...
			0.18.1
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 4b26a92b37 | |||
| 0a8453b4d2 | |||
| c9872a61b6 | |||
| 149a1aa278 | |||
| 13d0e1b682 | |||
| 6f9be2a9f8 | |||
| 93ba98d993 | 
@@ -1,5 +1,12 @@
 | 
				
			|||||||
# Changelog
 | 
					# Changelog
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## 0.18.1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					* `Common`:
 | 
				
			||||||
 | 
					    * Add `MapDiff`
 | 
				
			||||||
 | 
					* `Coroutines`:
 | 
				
			||||||
 | 
					    * Add `SmartMutex`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## 0.18.0
 | 
					## 0.18.0
 | 
				
			||||||
 | 
					
 | 
				
			||||||
**ALL PREVIOUSLY DEPRECATED FUNCTIONALITY HAVE BEEN REMOVED**
 | 
					**ALL PREVIOUSLY DEPRECATED FUNCTIONALITY HAVE BEEN REMOVED**
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -200,20 +200,18 @@ inline fun <T> Iterable<T>.calculateStrictDiff(
 | 
				
			|||||||
) = calculateDiff(other, strictComparison = true)
 | 
					) = calculateDiff(other, strictComparison = true)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * This method call [calculateDiff] with strict mode [strictComparison] and then apply differences to [this]
 | 
					 * Applies [diff] to [this] [MutableList]
 | 
				
			||||||
 * mutable list
 | 
					 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
fun <T> MutableList<T>.applyDiff(
 | 
					fun <T> MutableList<T>.applyDiff(
 | 
				
			||||||
    source: Iterable<T>,
 | 
					    diff: Diff<T>
 | 
				
			||||||
    strictComparison: Boolean = false
 | 
					) {
 | 
				
			||||||
): Diff<T> = calculateDiff(source, strictComparison).also {
 | 
					    for (i in diff.removed.indices.sortedDescending()) {
 | 
				
			||||||
    for (i in it.removed.indices.sortedDescending()) {
 | 
					        removeAt(diff.removed[i].index)
 | 
				
			||||||
        removeAt(it.removed[i].index)
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    it.added.forEach { (i, t) ->
 | 
					    diff.added.forEach { (i, t) ->
 | 
				
			||||||
        add(i, t)
 | 
					        add(i, t)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    it.replaced.forEach { (_, new) ->
 | 
					    diff.replaced.forEach { (_, new) ->
 | 
				
			||||||
        set(new.index, new.value)
 | 
					        set(new.index, new.value)
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
@@ -222,17 +220,30 @@ fun <T> MutableList<T>.applyDiff(
 | 
				
			|||||||
 * This method call [calculateDiff] with strict mode [strictComparison] and then apply differences to [this]
 | 
					 * This method call [calculateDiff] with strict mode [strictComparison] and then apply differences to [this]
 | 
				
			||||||
 * mutable list
 | 
					 * mutable list
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					fun <T> MutableList<T>.applyDiff(
 | 
				
			||||||
 | 
					    source: Iterable<T>,
 | 
				
			||||||
 | 
					    strictComparison: Boolean = false
 | 
				
			||||||
 | 
					): Diff<T> = calculateDiff(source, strictComparison).also {
 | 
				
			||||||
 | 
					    applyDiff(it)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This method call [calculateDiff] and then apply differences to [this]
 | 
				
			||||||
 | 
					 * mutable list
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
fun <T> MutableList<T>.applyDiff(
 | 
					fun <T> MutableList<T>.applyDiff(
 | 
				
			||||||
    source: Iterable<T>,
 | 
					    source: Iterable<T>,
 | 
				
			||||||
    comparisonFun: (T?, T?) -> Boolean
 | 
					    comparisonFun: (T?, T?) -> Boolean
 | 
				
			||||||
): Diff<T> = calculateDiff(source, comparisonFun).also {
 | 
					): Diff<T> = calculateDiff(source, comparisonFun).also {
 | 
				
			||||||
    for (i in it.removed.indices.sortedDescending()) {
 | 
					    applyDiff(it)
 | 
				
			||||||
        removeAt(it.removed[i].index)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    it.added.forEach { (i, t) ->
 | 
					 | 
				
			||||||
        add(i, t)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    it.replaced.forEach { (_, new) ->
 | 
					 | 
				
			||||||
        set(new.index, new.value)
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reverse [this] [Diff]. Result will contain [Diff.added] on [Diff.removed] (and vice-verse), all the
 | 
				
			||||||
 | 
					 * [Diff.replaced] values will be reversed too
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun <T> Diff<T>.reversed() = Diff(
 | 
				
			||||||
 | 
					    removed = added,
 | 
				
			||||||
 | 
					    replaced = replaced.map { it.second to it.first },
 | 
				
			||||||
 | 
					    added = removed
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -0,0 +1,135 @@
 | 
				
			|||||||
 | 
					package dev.inmo.micro_utils.common
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Contains diff based on the comparison of objects with the same [K].
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param removed Contains map with keys removed from parent map
 | 
				
			||||||
 | 
					 * @param changed Contains map with keys values changed new map in comparison with old one
 | 
				
			||||||
 | 
					 * @param added Contains map with new keys and values
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					data class MapDiff<K, V> @Warning(warning) constructor(
 | 
				
			||||||
 | 
					    val removed: Map<K, V>,
 | 
				
			||||||
 | 
					    val changed: Map<K, Pair<V, V>>,
 | 
				
			||||||
 | 
					    val added: Map<K, V>
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    fun isEmpty() = removed.isEmpty() && changed.isEmpty() && added.isEmpty()
 | 
				
			||||||
 | 
					    inline fun isNotEmpty() = !isEmpty()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    companion object {
 | 
				
			||||||
 | 
					        private const val warning = "This feature can be changed without any warranties. Use with caution and only in case you know what you are doing"
 | 
				
			||||||
 | 
					        fun <K, V> empty() = MapDiff<K, V>(emptyMap(), emptyMap(), emptyMap())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					private inline fun <K, V> createCompareFun(
 | 
				
			||||||
 | 
					    strictComparison: Boolean
 | 
				
			||||||
 | 
					): (K, V, V) -> Boolean = if (strictComparison) {
 | 
				
			||||||
 | 
					    { _, first, second -> first === second }
 | 
				
			||||||
 | 
					} else {
 | 
				
			||||||
 | 
					    { _, first, second -> first == second }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compare [this] [Map] with the [other] one in principle when [other] is newer than [this]
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param compareFun Will be used to determine changed values
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun <K, V> Map<K, V>.diff(
 | 
				
			||||||
 | 
					    other: Map<K, V>,
 | 
				
			||||||
 | 
					    compareFun: (K, V, V) -> Boolean
 | 
				
			||||||
 | 
					): MapDiff<K, V> {
 | 
				
			||||||
 | 
					    val removed: Map<K, V> = (keys - other.keys).associateWith {
 | 
				
			||||||
 | 
					        getValue(it)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    val added: Map<K, V> = (other.keys - keys).associateWith {
 | 
				
			||||||
 | 
					        other.getValue(it)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    val changed = keys.intersect(other.keys).mapNotNull {
 | 
				
			||||||
 | 
					        val old = getValue(it)
 | 
				
			||||||
 | 
					        val new = other.getValue(it)
 | 
				
			||||||
 | 
					        if (compareFun(it, old, new)) {
 | 
				
			||||||
 | 
					            return@mapNotNull null
 | 
				
			||||||
 | 
					        } else {
 | 
				
			||||||
 | 
					            it to (old to new)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }.toMap()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return MapDiff(
 | 
				
			||||||
 | 
					        removed,
 | 
				
			||||||
 | 
					        changed,
 | 
				
			||||||
 | 
					        added
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Compare [this] [Map] with the [other] one in principle when [other] is newer than [this]
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param strictComparison If true, will use strict (===) comparison for the values' comparison. Otherwise, standard
 | 
				
			||||||
 | 
					 * `equals` will be used
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun <K, V> Map<K, V>.diff(
 | 
				
			||||||
 | 
					    other: Map<K, V>,
 | 
				
			||||||
 | 
					    strictComparison: Boolean = false
 | 
				
			||||||
 | 
					): MapDiff<K, V> = diff(
 | 
				
			||||||
 | 
					    other,
 | 
				
			||||||
 | 
					    compareFun = createCompareFun(strictComparison)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Will apply [mapDiff] to [this] [MutableMap]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun <K, V> MutableMap<K, V>.applyDiff(
 | 
				
			||||||
 | 
					    mapDiff: MapDiff<K, V>
 | 
				
			||||||
 | 
					) {
 | 
				
			||||||
 | 
					    mapDiff.apply {
 | 
				
			||||||
 | 
					        removed.keys.forEach { remove(it) }
 | 
				
			||||||
 | 
					        changed.forEach { (k, oldNew) ->
 | 
				
			||||||
 | 
					            put(k, oldNew.second)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        added.forEach { (k, new) ->
 | 
				
			||||||
 | 
					            put(k, new)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Will apply changes with [from] map into [this] one
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param compareFun Will be used to determine changed values
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return [MapDiff] applied to [this] [MutableMap]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun <K, V> MutableMap<K, V>.applyDiff(
 | 
				
			||||||
 | 
					    from: Map<K, V>,
 | 
				
			||||||
 | 
					    compareFun: (K, V, V) -> Boolean
 | 
				
			||||||
 | 
					): MapDiff<K, V> {
 | 
				
			||||||
 | 
					    return diff(from, compareFun).also {
 | 
				
			||||||
 | 
					        applyDiff(it)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Will apply changes with [from] map into [this] one
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @param strictComparison If true, will use strict (===) comparison for the values' comparison. Otherwise, standard
 | 
				
			||||||
 | 
					 * `equals` will be used
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * @return [MapDiff] applied to [this] [MutableMap]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun <K, V> MutableMap<K, V>.applyDiff(
 | 
				
			||||||
 | 
					    from: Map<K, V>,
 | 
				
			||||||
 | 
					    strictComparison: Boolean = false
 | 
				
			||||||
 | 
					): MapDiff<K, V> = applyDiff(
 | 
				
			||||||
 | 
					    from,
 | 
				
			||||||
 | 
					    compareFun = createCompareFun(strictComparison)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Reverse [this] [MapDiff]. Result will contain [MapDiff.added] on [MapDiff.removed] (and vice-verse), all the
 | 
				
			||||||
 | 
					 * [MapDiff.changed] values will be reversed too
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					fun <K, V> MapDiff<K, V>.reversed(): MapDiff<K, V> = MapDiff(
 | 
				
			||||||
 | 
					    removed = added,
 | 
				
			||||||
 | 
					    changed = changed.mapValues { (_, oldNew) -> oldNew.second to oldNew.first },
 | 
				
			||||||
 | 
					    added = removed
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
@@ -0,0 +1,136 @@
 | 
				
			|||||||
 | 
					package dev.inmo.micro_utils.coroutines
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import kotlinx.coroutines.currentCoroutineContext
 | 
				
			||||||
 | 
					import kotlinx.coroutines.flow.MutableStateFlow
 | 
				
			||||||
 | 
					import kotlinx.coroutines.flow.StateFlow
 | 
				
			||||||
 | 
					import kotlinx.coroutines.flow.asStateFlow
 | 
				
			||||||
 | 
					import kotlinx.coroutines.flow.first
 | 
				
			||||||
 | 
					import kotlinx.coroutines.isActive
 | 
				
			||||||
 | 
					import kotlinx.coroutines.sync.Mutex
 | 
				
			||||||
 | 
					import kotlinx.coroutines.sync.withLock
 | 
				
			||||||
 | 
					import kotlin.contracts.ExperimentalContracts
 | 
				
			||||||
 | 
					import kotlin.contracts.InvocationKind
 | 
				
			||||||
 | 
					import kotlin.contracts.contract
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * It is interface which will work like classic [Mutex], but in difference have [lockStateFlow] for listening of the
 | 
				
			||||||
 | 
					 * [SmartMutex] state.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * There is [Mutable] and [Immutable] realizations. In case you are owner and manager current state of lock, you need
 | 
				
			||||||
 | 
					 * [Mutable] [SmartMutex]. Otherwise, [Immutable].
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Any [Mutable] [SmartMutex] may produce its [Immutable] variant which will contains [lockStateFlow] equal to its
 | 
				
			||||||
 | 
					 * [Mutable] creator
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					sealed interface SmartMutex {
 | 
				
			||||||
 | 
					    val lockStateFlow: StateFlow<Boolean>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * * True - locked
 | 
				
			||||||
 | 
					     * * False - unlocked
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    val isLocked: Boolean
 | 
				
			||||||
 | 
					        get() = lockStateFlow.value
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Immutable variant of [SmartMutex]. In fact will depend on the owner of [lockStateFlow]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    class Immutable(override val lockStateFlow: StateFlow<Boolean>) : SmartMutex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * Mutable variant of [SmartMutex]. With that variant you may [lock] and [unlock]. Besides, you may create
 | 
				
			||||||
 | 
					     * [Immutable] variant of [this] instance with [immutable] factory
 | 
				
			||||||
 | 
					     *
 | 
				
			||||||
 | 
					     * @param locked Preset state of [isLocked] and its internal [_lockStateFlow]
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    class Mutable(locked: Boolean = false) : SmartMutex {
 | 
				
			||||||
 | 
					        private val _lockStateFlow = MutableStateFlow<Boolean>(locked)
 | 
				
			||||||
 | 
					        override val lockStateFlow: StateFlow<Boolean> = _lockStateFlow.asStateFlow()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        private val internalChangesMutex = Mutex()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fun immutable() = Immutable(lockStateFlow)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Holds call until this [SmartMutex] will be re-locked. That means that while [isLocked] == true, [holds] will
 | 
				
			||||||
 | 
					         * wait for [isLocked] == false and then try to lock
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        suspend fun lock() {
 | 
				
			||||||
 | 
					            do {
 | 
				
			||||||
 | 
					                waitUnlock()
 | 
				
			||||||
 | 
					                val shouldContinue = internalChangesMutex.withLock {
 | 
				
			||||||
 | 
					                    if (_lockStateFlow.value) {
 | 
				
			||||||
 | 
					                        true
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        _lockStateFlow.value = true
 | 
				
			||||||
 | 
					                        false
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } while (shouldContinue && currentCoroutineContext().isActive)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * Will try to lock this [SmartMutex] immediataly
 | 
				
			||||||
 | 
					         *
 | 
				
			||||||
 | 
					         * @return True if lock was successful. False otherwise
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        suspend fun tryLock(): Boolean {
 | 
				
			||||||
 | 
					            return if (!_lockStateFlow.value) {
 | 
				
			||||||
 | 
					                internalChangesMutex.withLock {
 | 
				
			||||||
 | 
					                    if (!_lockStateFlow.value) {
 | 
				
			||||||
 | 
					                        _lockStateFlow.value = true
 | 
				
			||||||
 | 
					                        true
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        false
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        /**
 | 
				
			||||||
 | 
					         * If [isLocked] == true - will change it to false and return true. If current call will not unlock this
 | 
				
			||||||
 | 
					         * [SmartMutex] - false
 | 
				
			||||||
 | 
					         */
 | 
				
			||||||
 | 
					        suspend fun unlock(): Boolean {
 | 
				
			||||||
 | 
					            return if (_lockStateFlow.value) {
 | 
				
			||||||
 | 
					                internalChangesMutex.withLock {
 | 
				
			||||||
 | 
					                    if (_lockStateFlow.value) {
 | 
				
			||||||
 | 
					                        _lockStateFlow.value = false
 | 
				
			||||||
 | 
					                        true
 | 
				
			||||||
 | 
					                    } else {
 | 
				
			||||||
 | 
					                        false
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            } else {
 | 
				
			||||||
 | 
					                false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Will call [SmartMutex.Mutable.lock], then execute [action] and return the result after [SmartMutex.Mutable.unlock]
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					@OptIn(ExperimentalContracts::class)
 | 
				
			||||||
 | 
					suspend inline fun <T> SmartMutex.Mutable.withLock(action: () -> T): T {
 | 
				
			||||||
 | 
					    contract {
 | 
				
			||||||
 | 
					        callsInPlace(action, InvocationKind.EXACTLY_ONCE)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    lock()
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					        return action()
 | 
				
			||||||
 | 
					    } finally {
 | 
				
			||||||
 | 
					        unlock()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Will wait until the [SmartMutex.lockStateFlow] of [this] instance will be false.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Anyway, after the end of this block there are no any guaranties that [SmartMutex.isLocked] == false due to the fact
 | 
				
			||||||
 | 
					 * that some other parties may lock it again
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					suspend fun SmartMutex.waitUnlock() = lockStateFlow.first { !it }
 | 
				
			||||||
@@ -14,5 +14,5 @@ crypto_js_version=4.1.1
 | 
				
			|||||||
# Project data
 | 
					# Project data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
group=dev.inmo
 | 
					group=dev.inmo
 | 
				
			||||||
version=0.18.0
 | 
					version=0.18.1
 | 
				
			||||||
android_code_version=191
 | 
					android_code_version=192
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user