diff --git a/src/main/kotlin/cn/tursom/core/datastruct/ArrayMap.kt b/src/main/kotlin/cn/tursom/core/datastruct/ArrayMap.kt index 34cb6d6..d7dd2f7 100644 --- a/src/main/kotlin/cn/tursom/core/datastruct/ArrayMap.kt +++ b/src/main/kotlin/cn/tursom/core/datastruct/ArrayMap.kt @@ -1,271 +1,284 @@ package cn.tursom.core.datastruct +import cn.tursom.core.cast + @Suppress("MemberVisibilityCanBePrivate") -class ArrayMap<K : Comparable<K>, V>(initialCapacity: Int = 16) : SimpMap<K, V> { - @Volatile - private var arr: Array<Node<K, V>?> = Array(initialCapacity) { null } - @Volatile - private var end = 0 +open class ArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> { + @Volatile + protected var arr: Array<Node<K, V>?> = Array(initialCapacity) { null } - override val size: Int get() = end - override val entries: MutableSet<MutableMap.MutableEntry<K, V>> = EntrySet(this) - override val keys: MutableSet<K> = KeySet(this) - override val values: MutableCollection<V> = ValueCollection(this) + @Volatile + protected var end = 0 - /** - * @param key 查找的键 - * @return 键所在的下标 - * @return < 0 如果键不存在, -${return} - 1 为如果插入应插入的下标 - */ - fun search(key: K): Int { - if (end == 0) return -1 - return arr.binarySearch(key, 0, end) + override val size: Int get() = end + override val entries: MutableSet<MutableMap.MutableEntry<K, V>> = EntrySet(this) + override val keys: MutableSet<K> = KeySet(this) + override val values: MutableCollection<V> = ValueCollection(this) + + /** + * @param key 查找的键 + * @return 键所在的下标 + * @return < 0 如果键不存在, -${return} - 1 为如果插入应插入的下标 + */ + open fun search(key: K): Int { + if (end == 0) return -1 + for (index in 0 until end) { + if ((arr[index] ?: continue).key == key) { + return index + } + } + return -1 + } + + infix fun getFromIndex(index: Int): V? { + return if (index < 0) null + else arr[index]?.value + } + + override fun first(): V? = getFromIndex(0) + + override fun clear() { + end = 0 + } + + override operator fun set(key: K, value: V) { + setAndGet(key, value) + } + + override fun setAndGet(key: K, value: V): V? { + @Suppress("SENSELESS_COMPARISON") + if (key == null) return null + // 首先查找得到目标所在的下标 + val index = search(key) + var prev: V? = null + if (index < 0) { + // 下标小于零表示不存在,直接插入数据 + insert(key, value, -index - 1) + } else { + val node = arr[index] + if (node != null) { + prev = node.value + node.value = value + } else arr[index] = Node(key, value) + } + return prev + } + + override infix fun putAll(from: Map<out K, V>) { + from.forEach { (key, value) -> + val index = search(key) + if (index < 0) arr[end++] = Node(key, value) + else { + val node = arr[index] + if (node != null) node.value = value + else arr[index] = Node(key, value) + } + } + } + + override infix fun delete(key: K): V? { + val index = search(key) + return delete(index) + } + + override infix fun containsKey(key: K): Boolean = search(key) >= 0 + + override infix fun containsValue(value: V): Boolean { + arr.forEach { + if (it?.value == value) return true + } + return false + } + + override infix operator fun get(key: K): V? = getNode(key)?.value + override fun isEmpty(): Boolean = end == 0 + + fun copy(): ArrayMap<K, V> { + val clone = ArrayMap<K, V>(0) + clone.arr = Array(end) { arr[it]?.let { Node(it.key, it.value) } } + clone.end = end + return clone + } + + override fun toString(): String { + if (end == 0) return "{}" + val sb = StringBuilder("{${arr[0]}") + for (i in 1 until end) { + sb.append(", ") + sb.append(arr[i]) + } + sb.append("}") + return sb.toString() + } + + private fun getNode(key: K): Node<K, V>? { + @Suppress("SENSELESS_COMPARISON") + if (key == null) return null + val index = search(key) + return if (index < 0) null + else arr[index] + } + + private fun resize(newSize: Int = if (arr.isNotEmpty()) arr.size * 2 else 1) { + arr = arr.copyOf(newSize) + } + + private fun insert(key: K, value: V, index: Int): V? { + if (end == arr.size) resize() + System.arraycopy(arr, index, arr, index + 1, end - index) + arr[index] = Node(key, value) + end++ + return value + } + + private infix fun delete(index: Int): V? { + if (index in 0 until end) { + val oldNode = arr[index] + System.arraycopy(arr, index + 1, arr, index, end - index - 1) + end-- + return oldNode?.value + } + return null + } + + class Node<K, V>( + override val key: K, + @Volatile override var value: V + ) : MutableMap.MutableEntry<K, V>, Comparable<K> { + override fun toString(): String = "$key=$value" + override fun setValue(newValue: V): V = value.also { value = newValue } + override fun compareTo(other: K): Int { + return if (key is Comparable<*>) { + key.cast<Comparable<K>>().compareTo(other) + } else { + -1 + } + } + } + + + class EntrySet<K, V>(private val map: ArrayMap<K, V>) : MutableSet<MutableMap.MutableEntry<K, V>> { + override val size: Int get() = map.size + override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean = map[element.key] == element.value + override fun isEmpty(): Boolean = map.isEmpty() + override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = MapIterator(map) + override fun clear() = map.clear() + + override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + elements.forEach { + if (!contains(it)) return false + } + return true } - infix fun getFromIndex(index: Int): V? { - return if (index < 0) null - else arr[index]?.value + override fun add(element: MutableMap.MutableEntry<K, V>): Boolean { + map[element.key] = element.value + return true } - override fun first(): V? = getFromIndex(0) - - override fun clear() { - end = 0 + override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + elements.forEach { add(it) } + return true } - override operator fun set(key: K, value: V) { - setAndGet(key, value) + override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean { + val index = map.search(element.key) + val value = map.getFromIndex(index) + return if (value == element.value) { + map.delete(index) + true + } else { + false + } } - override fun setAndGet(key: K, value: V): V? { - @Suppress("SENSELESS_COMPARISON") - if (key == null) return null - // 首先查找得到目标所在的下标 - val index = search(key) - var prev: V? = null - if (index < 0) { - // 下标小于零表示不存在,直接插入数据 - insert(key, value, -index - 1) - } else { - val node = arr[index] - if (node != null) { - prev = node.value - node.value = value - } else arr[index] = Node(key, value) - } - return prev + override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + elements.forEach { remove(it) } + return true } - override infix fun putAll(from: Map<out K, V>) { - from.forEach { (key, value) -> - val index = search(key) - if (index < 0) arr[end++] = Node(key, value) - else { - val node = arr[index] - if (node != null) node.value = value - else arr[index] = Node(key, value) - } - } - arr.sort() + override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + val contains = elements.filter { map[it.key] == it.value } + map.clear() + map.resize(contains.size) + addAll(contains) + return true + } + } + + class MapIterator<K, V>(private val map: ArrayMap<K, V>) : MutableIterator<MutableMap.MutableEntry<K, V>> { + private var index = 0 + + override fun hasNext(): Boolean { + @Suppress("ControlFlowWithEmptyBody") + while (++index < map.arr.size && index < map.end && map.arr[index] == null); + index-- + return index < map.end } - override infix fun delete(key: K): V? { - val index = search(key) - return delete(index) + override fun next(): MutableMap.MutableEntry<K, V> = map.arr[index++]!! + + override fun remove() { + map.delete(index) + index-- + } + } + + class KeySet<K>(private val map: ArrayMap<K, *>) : MutableSet<K> { + override val size: Int get() = map.size + override fun contains(element: K): Boolean = map.containsKey(element) + override fun isEmpty(): Boolean = size == 0 + override fun iterator(): MutableIterator<K> = KeyIterator(map) + + override fun containsAll(elements: Collection<K>): Boolean { + elements.forEach { + if (!map.containsKey(it)) return false + } + return true } - override infix fun containsKey(key: K): Boolean = search(key) >= 0 - - override infix fun containsValue(value: V): Boolean { - arr.forEach { - if (it?.value == value) return true - } - return false + override fun add(element: K): Boolean = false + override fun addAll(elements: Collection<K>): Boolean = false + override fun clear() = map.clear() + override fun retainAll(elements: Collection<K>): Boolean = map.entries.retainAll(elements.map { map.getNode(it) }.filterNotNull()) + override fun remove(element: K): Boolean = map.remove(element) != null + override fun removeAll(elements: Collection<K>): Boolean { + elements.forEach { remove(it) } + return true } + } - override infix operator fun get(key: K): V? = getNode(key)?.value - override fun isEmpty(): Boolean = end == 0 + class KeyIterator<K>(map: ArrayMap<K, *>) : MutableIterator<K> { + private val iterator = map.iterator() + override fun hasNext(): Boolean = iterator.hasNext() + override fun next(): K = iterator.next().key + override fun remove() = iterator.remove() + } - fun copy(): ArrayMap<K, V> { - val clone = ArrayMap<K, V>(0) - clone.arr = Array(end) { arr[it]?.let { Node(it.key, it.value) } } - clone.end = end - return clone + class ValueCollection<V>(private val map: ArrayMap<*, V>) : MutableCollection<V> { + override val size: Int get() = map.size + override fun contains(element: V): Boolean = map.containsValue(element) + override fun isEmpty(): Boolean = size == 0 + override fun iterator(): MutableIterator<V> = ValueIterator(map) + override fun add(element: V): Boolean = false + override fun addAll(elements: Collection<V>): Boolean = false + override fun clear() = map.clear() + override fun remove(element: V): Boolean = false + override fun removeAll(elements: Collection<V>): Boolean = false + override fun retainAll(elements: Collection<V>): Boolean = false + + override fun containsAll(elements: Collection<V>): Boolean { + elements.forEach { + if (!map.containsValue(it)) return false + } + return true } + } - override fun toString(): String { - if (end == 0) return "{}" - val sb = StringBuilder("{${arr[0]}") - for (i in 1 until end) { - sb.append(", ") - sb.append(arr[i]) - } - sb.append("}") - return sb.toString() - } - - private fun getNode(key: K): Node<K, V>? { - @Suppress("SENSELESS_COMPARISON") - if (key == null) return null - val index = search(key) - return if (index < 0) null - else arr[index] - } - - private fun resize(newSize: Int = if (arr.isNotEmpty()) arr.size * 2 else 1) { - arr = arr.copyOf(newSize) - } - - private fun insert(key: K, value: V, index: Int): V? { - if (end == arr.size) resize() - System.arraycopy(arr, index, arr, index + 1, end - index) - arr[index] = Node(key, value) - end++ - return value - } - - private infix fun delete(index: Int): V? { - if (index in 0 until end) { - val oldNode = arr[index] - System.arraycopy(arr, index + 1, arr, index, end - index - 1) - end-- - return oldNode?.value - } - return null - } - - class Node<K : Comparable<K>, V>( - override val key: K, - @Volatile override var value: V - ) : Comparable<K>, MutableMap.MutableEntry<K, V> { - override fun compareTo(other: K): Int = key.compareTo(other) - override fun toString(): String = "$key=$value" - override fun setValue(newValue: V): V = value.also { value = newValue } - } - - - class EntrySet<K : Comparable<K>, V>(private val map: ArrayMap<K, V>) : MutableSet<MutableMap.MutableEntry<K, V>> { - override val size: Int get() = map.size - override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean = map[element.key] == element.value - override fun isEmpty(): Boolean = map.isEmpty() - override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = MapIterator(map) - override fun clear() = map.clear() - - override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { - elements.forEach { - if (!contains(it)) return false - } - return true - } - - override fun add(element: MutableMap.MutableEntry<K, V>): Boolean { - map[element.key] = element.value - return true - } - - override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { - elements.forEach { add(it) } - return true - } - - override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean { - val index = map.search(element.key) - val value = map.getFromIndex(index) - return if (value == element.value) { - map.delete(index) - true - } else { - false - } - } - - override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { - elements.forEach { remove(it) } - return true - } - - override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { - val contains = elements.filter { map[it.key] == it.value } - map.clear() - map.resize(contains.size) - addAll(contains) - return true - } - } - - class MapIterator<K : Comparable<K>, V>(private val map: ArrayMap<K, V>) : MutableIterator<MutableMap.MutableEntry<K, V>> { - private var index = 0 - - override fun hasNext(): Boolean { - @Suppress("ControlFlowWithEmptyBody") - while (++index < map.arr.size && index < map.end && map.arr[index] == null); - index-- - return index < map.end - } - - override fun next(): MutableMap.MutableEntry<K, V> = map.arr[index++]!! - - override fun remove() { - map.delete(index) - index-- - } - } - - class KeySet<K : Comparable<K>>(private val map: ArrayMap<K, *>) : MutableSet<K> { - override val size: Int get() = map.size - override fun contains(element: K): Boolean = map.containsKey(element) - override fun isEmpty(): Boolean = size == 0 - override fun iterator(): MutableIterator<K> = KeyIterator(map) - - override fun containsAll(elements: Collection<K>): Boolean { - elements.forEach { - if (!map.containsKey(it)) return false - } - return true - } - - override fun add(element: K): Boolean = false - override fun addAll(elements: Collection<K>): Boolean = false - override fun clear() = map.clear() - override fun retainAll(elements: Collection<K>): Boolean = map.entries.retainAll(elements.map { map.getNode(it) }.filterNotNull()) - override fun remove(element: K): Boolean = map.remove(element) != null - override fun removeAll(elements: Collection<K>): Boolean { - elements.forEach { remove(it) } - return true - } - } - - class KeyIterator<K : Comparable<K>>(map: ArrayMap<K, *>) : MutableIterator<K> { - private val iterator = map.iterator() - override fun hasNext(): Boolean = iterator.hasNext() - override fun next(): K = iterator.next().key - override fun remove() = iterator.remove() - } - - class ValueCollection<V>(private val map: ArrayMap<*, V>) : MutableCollection<V> { - override val size: Int get() = map.size - override fun contains(element: V): Boolean = map.containsValue(element) - override fun isEmpty(): Boolean = size == 0 - override fun iterator(): MutableIterator<V> = ValueIterator(map) - override fun add(element: V): Boolean = false - override fun addAll(elements: Collection<V>): Boolean = false - override fun clear() = map.clear() - override fun remove(element: V): Boolean = false - override fun removeAll(elements: Collection<V>): Boolean = false - override fun retainAll(elements: Collection<V>): Boolean = false - - override fun containsAll(elements: Collection<V>): Boolean { - elements.forEach { - if (!map.containsValue(it)) return false - } - return true - } - } - - class ValueIterator<V>(map: ArrayMap<*, V>) : MutableIterator<V> { - private val iterator = map.iterator() - override fun hasNext(): Boolean = iterator.hasNext() - override fun next(): V = iterator.next().value - override fun remove() = iterator.remove() - } + class ValueIterator<V>(map: ArrayMap<*, V>) : MutableIterator<V> { + private val iterator = map.iterator() + override fun hasNext(): Boolean = iterator.hasNext() + override fun next(): V = iterator.next().value + override fun remove() = iterator.remove() + } } diff --git a/src/main/kotlin/cn/tursom/core/datastruct/ComparableArrayMap.kt b/src/main/kotlin/cn/tursom/core/datastruct/ComparableArrayMap.kt new file mode 100644 index 0000000..afcdaaf --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/ComparableArrayMap.kt @@ -0,0 +1,27 @@ +package cn.tursom.core.datastruct + +@Suppress("MemberVisibilityCanBePrivate") +class ComparableArrayMap<K : Comparable<K>, V>(initialCapacity: Int = 16) : ArrayMap<K, V>(initialCapacity) { + /** + * @param key 查找的键 + * @return 键所在的下标 + * @return < 0 如果键不存在, -${return} - 1 为如果插入应插入的下标 + */ + override fun search(key: K): Int { + if (end == 0) return -1 + return arr.binarySearch(key, 0, end) + } + + override infix fun putAll(from: Map<out K, V>) { + from.forEach { (key, value) -> + val index = search(key) + if (index < 0) arr[end++] = Node(key, value) + else { + val node = arr[index] + if (node != null) node.value = value + else arr[index] = Node(key, value) + } + } + arr.sort() + } +} diff --git a/src/main/kotlin/cn/tursom/core/datastruct/ParallelArrayMap.kt b/src/main/kotlin/cn/tursom/core/datastruct/ParallelArrayMap.kt new file mode 100644 index 0000000..029b6b3 --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/datastruct/ParallelArrayMap.kt @@ -0,0 +1,203 @@ +package cn.tursom.core.datastruct + +import cn.tursom.core.cast + +@Suppress("MemberVisibilityCanBePrivate") +open class ParallelArrayMap<K, V>(initialCapacity: Int = 16) : SimpMap<K, V> { + @Volatile + protected var arr: Array<Any?> = Array(initialCapacity) { null } + + @Volatile + protected var arrValue: Array<Any?> = Array(initialCapacity) { null } + + @Volatile + protected var end = 0 + + override val size: Int get() = end + + @Suppress("LeakingThis") + override val entries: MutableSet<MutableMap.MutableEntry<K, V>> = EntrySet(this) + override val keys: MutableSet<K> get() = arrValue.asList().subList(0, end).toMutableSet().cast() + override val values: MutableCollection<V> get() = arrValue.asList().cast<MutableList<V>>().subList(0, end) + + /** + * @param key 查找的键 + * @return 键所在的下标 + * @return < 0 如果键不存在, -${return} - 1 为如果插入应插入的下标 + */ + open fun search(key: K): Int { + if (end == 0) return -1 + for (index in 0 until end) { + if ((arr[index] ?: continue) == key) { + return index + } + } + return -1 + } + + private fun resize(newSize: Int = if (arr.isNotEmpty()) arr.size * 2 else 1) { + arr = arr.copyOf(newSize) + arrValue = arrValue.copyOf(newSize) + } + + override fun setAndGet(key: K, value: V): V? { + var index = search(key) + if (index < 0 || index >= end) { + if (end == arr.size) { + resize() + } + index = end++ + arr[index] = key + } + return setByIndex(index, value) + } + + override fun set(key: K, value: V) { + setAndGet(key, value) + } + + fun setByIndex(index: Int, value: V): V? { + val oldValue = arrValue[end] + arrValue[index] = value + return oldValue.cast() + } + + override fun delete(key: K): V? { + return deleteByIndex(search(key)) + } + + fun deleteByIndex(index: Int): V? { + if (index < 0 || index >= end) return null + val oldValue = arrValue[index] + System.arraycopy(arr, index + 1, arr, index, end - index - 1) + System.arraycopy(arrValue, index + 1, arrValue, index, end - index - 1) + end-- + return oldValue.cast() + } + + override fun clear() { + end = 0 + } + + override fun first(): V? { + return if (end <= 0) { + null + } else { + arrValue[0].cast() + } + } + + override fun containsKey(key: K): Boolean { + return search(key) >= 0 + } + + override fun containsValue(value: V): Boolean { + if (end == 0) return false + for (index in 0 until end) { + if ((arrValue[index] ?: continue) == value) { + return true + } + } + return false + } + + override fun get(key: K): V? { + return getByIndex(search(key)) + } + + fun getKeyByIndex(index: Int): K? { + return if (index < 0 || index >= end) { + null + } else { + arr[index].cast() + } + } + + fun getByIndex(index: Int): V? { + return if (index < 0 || index >= end) { + null + } else { + arrValue[index].cast() + } + } + + override fun isEmpty(): Boolean = end <= 0 + + class EntrySet<K, V>(private val map: ParallelArrayMap<K, V>) : MutableSet<MutableMap.MutableEntry<K, V>> { + override val size: Int get() = map.size + override fun contains(element: MutableMap.MutableEntry<K, V>): Boolean = map[element.key] == element.value + override fun isEmpty(): Boolean = map.isEmpty() + override fun iterator(): MutableIterator<MutableMap.MutableEntry<K, V>> = MapIterator(map) + override fun clear() = map.clear() + + override fun containsAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + elements.forEach { + if (!contains(it)) return false + } + return true + } + + override fun add(element: MutableMap.MutableEntry<K, V>): Boolean { + map[element.key] = element.value + return true + } + + override fun addAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + elements.forEach { add(it) } + return true + } + + override fun remove(element: MutableMap.MutableEntry<K, V>): Boolean { + val index = map.search(element.key) + val value = map.getByIndex(index) + return if (value == element.value) { + map.deleteByIndex(index) + true + } else { + false + } + } + + override fun removeAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + elements.forEach { remove(it) } + return true + } + + override fun retainAll(elements: Collection<MutableMap.MutableEntry<K, V>>): Boolean { + val contains = elements.filter { map[it.key] == it.value } + map.clear() + map.resize(contains.size) + addAll(contains) + return true + } + } + + class MapIterator<K, V>(private val map: ParallelArrayMap<K, V>) : MutableIterator<MutableMap.MutableEntry<K, V>> { + private var index = 0 + + override fun hasNext(): Boolean { + @Suppress("ControlFlowWithEmptyBody") + while (++index < map.arr.size && index < map.end && map.arr[index] == null); + index-- + return index < map.end + } + + override fun next(): MutableMap.MutableEntry<K, V> = ParallelArrayMapEntry(map, index++) + + override fun remove() { + map.deleteByIndex(index) + index-- + } + } + + class ParallelArrayMapEntry<K, V>( + val map: ParallelArrayMap<K, V>, + val index: Int + ) : MutableMap.MutableEntry<K, V> { + override val key: K get() = map.getKeyByIndex(index).cast() + override val value: V get() = map.getByIndex(index).cast() + override fun setValue(newValue: V): V { + return map.setByIndex(index, newValue).cast() + } + } +} diff --git a/src/main/kotlin/cn/tursom/core/stream/impl/JavaInputStreamProxy.kt b/src/main/kotlin/cn/tursom/core/stream/impl/JavaInputStreamProxy.kt new file mode 100644 index 0000000..5239b16 --- /dev/null +++ b/src/main/kotlin/cn/tursom/core/stream/impl/JavaInputStreamProxy.kt @@ -0,0 +1,15 @@ +package cn.tursom.core.stream.impl + +import java.io.InputStream + +class JavaInputStreamProxy( + val inputStream: cn.tursom.core.stream.InputStream +) : InputStream() { + override fun read(): Int = inputStream.read() + override fun read(b: ByteArray, off: Int, len: Int): Int = inputStream.read(b, off, len) + + override fun skip(n: Long): Long { + inputStream.skip(n) + return n + } +} \ No newline at end of file diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocal.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocal.kt new file mode 100644 index 0000000..be9db7c --- /dev/null +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocal.kt @@ -0,0 +1,39 @@ +package cn.tursom.utils.coroutine + +import cn.tursom.core.cast +import kotlinx.coroutines.Job +import java.util.concurrent.ConcurrentHashMap +import kotlin.coroutines.coroutineContext + +open class CoroutineLocal<T> { + open suspend fun get(): T? { + var attach: MutableMap<CoroutineLocal<*>, Any?>? = coroutineContext[CoroutineLocalContext] + if (attach == null) { + val job = coroutineContext[Job] ?: return null + attach = attachMap[job] + } + return attach?.get(this)?.cast() + } + + open suspend infix fun set(value: T): Boolean { + var attach: MutableMap<CoroutineLocal<*>, Any?>? = coroutineContext[CoroutineLocalContext] + if (attach == null) { + val job = coroutineContext[Job] ?: return false + attach = attachMap[job] + if (attach == null) { + attach = HashMap() + attachMap[job] = attach + job.invokeOnCompletion { + attachMap.remove(job) + } + } + } + attach[this] = value + return true + } + + companion object { + private val attachMap = ConcurrentHashMap<Job, MutableMap<CoroutineLocal<*>, Any?>>() + override fun toString(): String = attachMap.toString() + } +} \ No newline at end of file diff --git a/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocalContext.kt b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocalContext.kt new file mode 100644 index 0000000..7f8cce1 --- /dev/null +++ b/utils/src/main/kotlin/cn/tursom/utils/coroutine/CoroutineLocalContext.kt @@ -0,0 +1,43 @@ +package cn.tursom.utils.coroutine + +import kotlinx.coroutines.* +import kotlin.coroutines.CoroutineContext +import kotlin.coroutines.EmptyCoroutineContext + +open class CoroutineLocalContext( + private val map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4) +) : CoroutineContext.Element, MutableMap<CoroutineLocal<*>, Any?> by map { + override val key: CoroutineContext.Key<*> get() = Companion + + override fun toString(): String { + return map.toString() + } + + companion object : CoroutineContext.Key<CoroutineLocalContext> +} + +fun CoroutineScope.launchWithCoroutineLocalContext( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4), + block: suspend CoroutineScope.() -> Unit +): Job { + return launch(context + CoroutineLocalContext(map), start, block) +} + +@Suppress("DeferredIsResult") +fun <T> CoroutineScope.asyncWithCoroutineLocalContext( + context: CoroutineContext = EmptyCoroutineContext, + start: CoroutineStart = CoroutineStart.DEFAULT, + map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4), + block: suspend CoroutineScope.() -> T +): Deferred<T> { + return async(context + CoroutineLocalContext(map), start, block) +} + +suspend fun <T> withCoroutineLocalContext( + map: MutableMap<CoroutineLocal<*>, Any?> = HashMap(4), + block: suspend CoroutineScope.() -> T +): T { + return withContext(CoroutineLocalContext(map), block) +} \ No newline at end of file diff --git a/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt b/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt new file mode 100644 index 0000000..5aecdbf --- /dev/null +++ b/utils/src/test/kotlin/cn/tursom/utils/coroutine/CoroutineLocalTest.kt @@ -0,0 +1,32 @@ +package cn.tursom.utils.coroutine + +import cn.tursom.core.usingTime +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.coroutineScope +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch + +val testCoroutineLocal = CoroutineLocal<Int>() +val testCoroutineLocalList = Array(100000) { + CoroutineLocal<Int>() +}.asList() + +suspend fun main() { + println(testCoroutineLocal.set(1)) + GlobalScope.launch { + coroutineScope { } + coroutineContext + testCoroutineLocal set 0 + testCoroutineLocal set 0 + testCoroutineLocalList.forEachIndexed { index, coroutineLocal -> + coroutineLocal set index + } + println(usingTime { + repeat(1000000000) { + testCoroutineLocal.get() + } + }) + }.join() + delay(1000) + println(CoroutineLocal) +} \ No newline at end of file