mirror of
https://github.com/tursom/TursomServer.git
synced 2025-03-25 09:00:07 +08:00
update kotlinx-coroutines-core version
This commit is contained in:
parent
8fbb4ea929
commit
7a90928246
@ -8,7 +8,7 @@ dependencies {
|
||||
api(project(":ts-core"))
|
||||
api(project(":ts-core:ts-buffer"))
|
||||
implementation(project(":ts-core:ts-xml"))
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
|
||||
api(group = "com.squareup.retrofit2", name = "converter-gson", version = "2.9.0")
|
||||
// https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit
|
||||
api(group = "com.squareup.retrofit2", name = "retrofit", version = "2.9.0")
|
||||
|
@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation(project(":ts-core"))
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
|
@ -5,7 +5,7 @@ plugins {
|
||||
|
||||
dependencies {
|
||||
implementation(project(":ts-core"))
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
|
@ -8,7 +8,7 @@ dependencies {
|
||||
implementation(project(":ts-core"))
|
||||
implementation(project(":ts-core:ts-datastruct"))
|
||||
implementation(project(":ts-core:ts-log"))
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||
api("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
|
||||
api(group = "org.mongodb", name = "mongodb-driver-reactivestreams", version = "4.0.5")
|
||||
}
|
||||
|
||||
|
@ -9,7 +9,7 @@ dependencies {
|
||||
implementation(project(":ts-core:ts-buffer"))
|
||||
implementation(project(":ts-core:ts-pool"))
|
||||
implementation(project(":ts-core:ts-log"))
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
|
@ -9,7 +9,7 @@ dependencies {
|
||||
implementation(project(":ts-core:ts-buffer"))
|
||||
implementation(project(":ts-core:ts-json"))
|
||||
implementation(group = "org.slf4j", name = "slf4j-api", version = "1.7.29")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2")
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.5.0")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
|
@ -1,12 +0,0 @@
|
||||
dependencies {
|
||||
compile project(":")
|
||||
api "com.google.code.gson:gson:2.8.2"
|
||||
// kotlin 协程
|
||||
api 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.4.2'
|
||||
// kotlin 反射
|
||||
api "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion"
|
||||
// 计算对象大小
|
||||
api 'org.apache.lucene:lucene-core:4.0.0'
|
||||
api group: "io.netty", name: "netty-all", version: "4.1.43.Final"
|
||||
api group: "io.netty", name: "netty-all", version: "4.1.43.Final"
|
||||
}
|
@ -1,36 +0,0 @@
|
||||
package cn.tursom.utils
|
||||
|
||||
import java.io.*
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
|
||||
object Gzip {
|
||||
fun compress(data: ByteArray): ByteArray {
|
||||
val out = ByteArrayOutputStream()
|
||||
compress(data, out)
|
||||
return out.toByteArray()
|
||||
}
|
||||
|
||||
fun compress(data: ByteArray, out: OutputStream) {
|
||||
val gzip = GZIPOutputStream(out)
|
||||
gzip.write(data)
|
||||
gzip.close()
|
||||
}
|
||||
|
||||
fun uncompress(bytes: ByteArray): ByteArray {
|
||||
return uncompress(ByteArrayInputStream(bytes)).readBytes()
|
||||
}
|
||||
|
||||
fun uncompress(inputStream: InputStream): InputStream {
|
||||
return GZIPInputStream(inputStream)
|
||||
}
|
||||
|
||||
class GzipBuilder(private val out: OutputStream = ByteArrayOutputStream()) : Closeable {
|
||||
private val gzip = GZIPOutputStream(out)
|
||||
fun write(byte: Int) = gzip.write(byte)
|
||||
fun write(bytes: ByteArray) = gzip.write(bytes)
|
||||
fun write(bytes: ByteArray, offset: Int, len: Int) = gzip.write(bytes, offset, len)
|
||||
fun get(): ByteArray = (out as ByteArrayOutputStream).toByteArray()
|
||||
override fun close() = gzip.close()
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
package cn.tursom.utils
|
||||
|
||||
import cn.tursom.core.base64
|
||||
import cn.tursom.core.base64decode
|
||||
import cn.tursom.core.digest
|
||||
import cn.tursom.core.toHexString
|
||||
import java.lang.Exception
|
||||
import kotlin.experimental.xor
|
||||
|
||||
|
||||
open class TokenUtil {
|
||||
@Suppress("MemberVisibilityCanBePrivate", "CanBeParameter")
|
||||
enum class DigestType(val digest: String) {
|
||||
MD5("MD5"), SHA256("SHA-256"), SHA512("SHA-512");
|
||||
|
||||
val digestBase64: String = digest.base64()
|
||||
}
|
||||
|
||||
fun <T : Token> generate(secretKey: String, data: T, type: DigestType = DigestType.MD5): String {
|
||||
val head = type.digestBase64
|
||||
val body = toJson(data).base64()
|
||||
val encryptSource = "$head.$body".toByteArray()
|
||||
val encrypt = encrypt(secretKey, encryptSource, type.digest)
|
||||
return "$head.$body.$encrypt"
|
||||
}
|
||||
|
||||
@Throws(TokenException::class)
|
||||
fun <T : Token> decode(secretKey: String, token: String, dataClazz: Class<T>): T {
|
||||
val splitToken = token.split(".")
|
||||
if (splitToken.size != 3) {
|
||||
throw WrongTokenSyntaxException()
|
||||
}
|
||||
val signature = encrypt(secretKey, "${splitToken[0]}.${splitToken[1]}".toByteArray(), splitToken[0].base64decode())
|
||||
if (signature != splitToken[2]) {
|
||||
throw WrongSignatureException()
|
||||
}
|
||||
val decode = fromJson(splitToken[1].base64decode(), dataClazz)
|
||||
if (decode.tim + decode.exp < System.currentTimeMillis()) {
|
||||
throw TokenTimeoutException()
|
||||
}
|
||||
return decode
|
||||
}
|
||||
|
||||
protected open fun encrypt(secretKey: String, encryptSource: ByteArray, type: String): String {
|
||||
val inner = secretKey.toByteArray().digest(type)!!
|
||||
encryptSource.forEachIndexed { index, _ ->
|
||||
encryptSource[index] = encryptSource[index] xor inner[index % inner.size]
|
||||
}
|
||||
val digest1 = encryptSource.digest(type)!!
|
||||
digest1.forEachIndexed { index, _ ->
|
||||
digest1[index] = digest1[index] xor inner[index % inner.size]
|
||||
}
|
||||
return digest1.digest(type)!!.toHexString()!!
|
||||
}
|
||||
|
||||
open fun toJson(bean: Any): String = gson.toJson(bean)
|
||||
open fun <T> fromJson(json: String, clazz: Class<T>): T = gson.fromJson(json, clazz)
|
||||
|
||||
interface Token {
|
||||
val tim: Long
|
||||
val exp: Long
|
||||
}
|
||||
|
||||
open class TokenException : Exception()
|
||||
class WrongTokenSyntaxException : TokenException()
|
||||
class WrongSignatureException : TokenException()
|
||||
class TokenTimeoutException : TokenException()
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val gsonTokenUtil = TokenUtil()
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package cn.tursom.utils
|
||||
|
||||
import com.google.gson.Gson
|
||||
import com.google.gson.GsonBuilder
|
||||
import com.google.gson.reflect.TypeToken
|
||||
import kotlinx.coroutines.*
|
||||
import java.util.concurrent.Executor
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.resumeWithException
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
@Suppress("unused", "SpellCheckingInspection")
|
||||
val gson = GsonBuilder()
|
||||
.registerTypeAdapterFactory(GsonDataTypeAdaptor.FACTORY)
|
||||
.create()
|
||||
|
||||
@Suppress("unused", "SpellCheckingInspection")
|
||||
val prettyGson = GsonBuilder()
|
||||
.registerTypeAdapterFactory(GsonDataTypeAdaptor.FACTORY)
|
||||
.setPrettyPrinting()
|
||||
.create()
|
||||
|
||||
fun Any.toJson(): String = gson.toJson(this)
|
||||
fun Any.toPrettyJson(): String = prettyGson.toJson(this)
|
||||
//inline fun <reified T : Any> String.fromJson(): T = gson.fromJson(this, T::class.java)
|
||||
|
||||
inline fun <reified T : Any> Gson.fromJson(json: String) = this.fromJson<T>(json, object : TypeToken<T>() {}.type)
|
||||
inline fun <reified T : Any> String.fromJson(gson: Gson = cn.tursom.utils.gson) = gson.fromJson<T>(this, object : TypeToken<T>() {}.type)!!
|
||||
|
||||
suspend fun <T> io(block: suspend CoroutineScope.() -> T): T {
|
||||
return withContext(Dispatchers.IO, block)
|
||||
}
|
||||
|
||||
fun background(block: suspend CoroutineScope.() -> Unit) {
|
||||
GlobalScope.launch(block = block)
|
||||
}
|
||||
|
||||
suspend fun <T> ui(block: suspend CoroutineScope.() -> T): T {
|
||||
return withContext(Dispatchers.Main, block)
|
||||
}
|
||||
|
||||
suspend operator fun <T> Executor.invoke(action: () -> T): T {
|
||||
return suspendCoroutine { exec ->
|
||||
execute {
|
||||
try {
|
||||
exec.resume(action())
|
||||
} catch (e: Throwable) {
|
||||
exec.resumeWithException(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,112 +0,0 @@
|
||||
package cn.tursom.utils.cache
|
||||
|
||||
import cn.tursom.utils.cache.interfaces.AsyncPotableCacheMap
|
||||
import cn.tursom.utils.datastruct.async.ReadWriteLockHashMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncCollection
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncSet
|
||||
import java.lang.ref.SoftReference
|
||||
|
||||
class AsyncSoftCacheMap<K, V>(
|
||||
val timeout: Long,
|
||||
private val valueMap: AsyncPotableMap<K, SoftReference<Pair<Long, V>>> = ReadWriteLockHashMap()
|
||||
) : AsyncPotableCacheMap<K, V> {
|
||||
override val size: Int
|
||||
get() = valueMap.size
|
||||
override val entries: AsyncSet<Map.Entry<K, V>> = Entries()
|
||||
override val keys: AsyncSet<K> = valueMap.keys
|
||||
override val values: AsyncCollection<V> = Values()
|
||||
|
||||
override suspend fun containsKey(key: K): Boolean = valueMap.containsKey(key)
|
||||
override suspend fun containsValue(value: V): Boolean = !valueMap.forEach { it.value != value }
|
||||
override suspend fun isEmpty(): Boolean = valueMap.isEmpty()
|
||||
|
||||
override suspend fun get(key: K): V? = getCache(key)
|
||||
|
||||
override suspend fun get(key: K, constructor: suspend () -> V): V {
|
||||
return get(key) ?: run {
|
||||
val newValue = constructor()
|
||||
addCache(key, newValue)
|
||||
newValue
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun set(key: K, value: V): V? {
|
||||
valueMap.set(key, SoftReference(System.currentTimeMillis() to value))
|
||||
return value
|
||||
}
|
||||
|
||||
override suspend fun putIfAbsent(key: K, value: V): Boolean {
|
||||
return valueMap.putIfAbsent(key, SoftReference(System.currentTimeMillis() to value))
|
||||
}
|
||||
|
||||
override suspend fun putAll(from: Map<out K, V>) {
|
||||
from.forEach { (k, v) ->
|
||||
valueMap.set(k, SoftReference(System.currentTimeMillis() to v))
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun remove(key: K): V? = valueMap.remove(key)?.get()?.second
|
||||
|
||||
override suspend fun clear() {
|
||||
valueMap.clear()
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
return valueMap.forEach {
|
||||
@Suppress("LABEL_NAME_CLASH")
|
||||
action(Entry(it.key, it.value.get()?.second ?: return@forEach true))
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun getCache(key: K): V? {
|
||||
val cache = valueMap.get(key)?.get() ?: return null
|
||||
if (cache.first.isTimeOut()) {
|
||||
delCache(key)
|
||||
return null
|
||||
}
|
||||
return cache.second
|
||||
}
|
||||
|
||||
private suspend fun delCache(key: K) {
|
||||
valueMap.remove(key)
|
||||
}
|
||||
|
||||
private suspend fun addCache(key: K, value: V) {
|
||||
valueMap.set(key, SoftReference(System.currentTimeMillis() to value))
|
||||
}
|
||||
|
||||
private fun Long?.isTimeOut() = this != null && timeout != 0L && System.currentTimeMillis() - this > timeout
|
||||
|
||||
data class Entry<K, V>(override val key: K, override val value: V) : Map.Entry<K, V>
|
||||
|
||||
inner class Entries : AsyncSet<Map.Entry<K, V>> {
|
||||
override val size: Int get() = valueMap.size
|
||||
|
||||
override suspend fun isEmpty(): Boolean = valueMap.isEmpty()
|
||||
|
||||
override suspend fun contains(element: Map.Entry<K, V>): Boolean = contains(element)
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<Map.Entry<K, V>>): Boolean = containsAll(elements)
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean =
|
||||
this@AsyncSoftCacheMap.forEach(action)
|
||||
}
|
||||
|
||||
inner class Values : AsyncCollection<V> {
|
||||
override val size: Int get() = valueMap.size
|
||||
override suspend fun isEmpty(): Boolean = valueMap.isEmpty()
|
||||
override suspend fun contains(element: V): Boolean = containsValue(element)
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<V>): Boolean {
|
||||
return elements.forEach { contains(it) }
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (V) -> Boolean): Boolean {
|
||||
return valueMap.forEach {
|
||||
@Suppress("LABEL_NAME_CLASH")
|
||||
action(it.value.get()?.second ?: return@forEach true)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,109 +0,0 @@
|
||||
package cn.tursom.utils.cache
|
||||
|
||||
import cn.tursom.utils.cache.interfaces.AsyncPotableCacheMap
|
||||
import cn.tursom.utils.datastruct.async.ReadWriteLockHashMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncCollection
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncSet
|
||||
|
||||
open class DefaultAsyncPotableCacheMap<K, V>(
|
||||
val timeout: Long,
|
||||
private val valueMap: AsyncPotableMap<K, Pair<Long, V>> = ReadWriteLockHashMap()
|
||||
) : AsyncPotableCacheMap<K, V> {
|
||||
override val size: Int
|
||||
get() = valueMap.size
|
||||
override val entries: AsyncSet<Map.Entry<K, V>> = Entries()
|
||||
override val keys: AsyncSet<K> = valueMap.keys
|
||||
override val values: AsyncCollection<V> = Values()
|
||||
|
||||
override suspend fun containsKey(key: K): Boolean = valueMap.containsKey(key)
|
||||
override suspend fun containsValue(value: V): Boolean = !valueMap.forEach { it.value != value }
|
||||
override suspend fun isEmpty(): Boolean = valueMap.isEmpty()
|
||||
|
||||
override suspend fun get(key: K): V? {
|
||||
val value = getCache(key) ?: return null
|
||||
return value
|
||||
}
|
||||
|
||||
override suspend fun get(key: K, constructor: suspend () -> V): V {
|
||||
val value = get(key) ?: run {
|
||||
val newValue = constructor()
|
||||
addCache(key, newValue)
|
||||
newValue
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
override suspend fun set(key: K, value: V): V? {
|
||||
valueMap.set(key, System.currentTimeMillis() to value)
|
||||
return value
|
||||
}
|
||||
|
||||
override suspend fun putIfAbsent(key: K, value: V): Boolean {
|
||||
return valueMap.putIfAbsent(key, System.currentTimeMillis() to value)
|
||||
}
|
||||
|
||||
override suspend fun putAll(from: Map<out K, V>) {
|
||||
from.forEach { (k, v) ->
|
||||
valueMap.set(k, System.currentTimeMillis() to v)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun remove(key: K): V? = valueMap.remove(key)?.second
|
||||
|
||||
override suspend fun clear() {
|
||||
valueMap.clear()
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
return valueMap.forEach { action(Entry(it.key, it.value.second)) }
|
||||
}
|
||||
|
||||
private suspend fun getCache(key: K): V? {
|
||||
val cache = valueMap.get(key) ?: return null
|
||||
if (cache.first.isTimeOut()) {
|
||||
delCache(key)
|
||||
return null
|
||||
}
|
||||
return cache.second
|
||||
}
|
||||
|
||||
private suspend fun delCache(key: K) {
|
||||
valueMap.remove(key)
|
||||
}
|
||||
|
||||
private suspend fun addCache(key: K, value: V) {
|
||||
valueMap.set(key, System.currentTimeMillis() to value)
|
||||
}
|
||||
|
||||
private fun Long.isTimeOut() = timeout != 0L && System.currentTimeMillis() - this > timeout
|
||||
|
||||
data class Entry<K, V>(override val key: K, override val value: V) : Map.Entry<K, V>
|
||||
|
||||
inner class Entries : AsyncSet<Map.Entry<K, V>> {
|
||||
override val size: Int get() = valueMap.size
|
||||
|
||||
override suspend fun isEmpty(): Boolean = valueMap.isEmpty()
|
||||
|
||||
override suspend fun contains(element: Map.Entry<K, V>): Boolean = contains(element)
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<Map.Entry<K, V>>): Boolean = containsAll(elements)
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean =
|
||||
this@DefaultAsyncPotableCacheMap.forEach(action)
|
||||
}
|
||||
|
||||
inner class Values : AsyncCollection<V> {
|
||||
override val size: Int get() = valueMap.size
|
||||
override suspend fun isEmpty(): Boolean = valueMap.isEmpty()
|
||||
override suspend fun contains(element: V): Boolean = containsValue(element)
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<V>): Boolean {
|
||||
return elements.forEach { contains(it) }
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (V) -> Boolean): Boolean {
|
||||
return valueMap.forEach { action(it.value.second) }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
package cn.tursom.utils.cache.interfaces
|
||||
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncMap
|
||||
|
||||
interface AsyncCacheMap<K, V> : AsyncMap<K, V> {
|
||||
suspend fun get(key: K, constructor: suspend () -> V): V
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
package cn.tursom.utils.cache.interfaces
|
||||
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
|
||||
interface AsyncPotableCacheMap<K, V> : AsyncCacheMap<K, V>, AsyncPotableMap<K, V>
|
@ -1,18 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncReadFirstRWLock
|
||||
import cn.tursom.utils.asynclock.AsyncWriteFirstRWLock
|
||||
import cn.tursom.utils.datastruct.async.collections.AsyncMapSet
|
||||
import cn.tursom.utils.datastruct.async.collections.AsyncRWLockAbstractMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
|
||||
|
||||
val <K : Comparable<K>> AsyncPotableMap<K, Unit>.keySet
|
||||
get() = AsyncMapSet(this)
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun <K, V> ReadWriteLockHashMap() = AsyncRWLockAbstractMap<K, V>(AsyncWriteFirstRWLock())
|
||||
|
||||
@Suppress("FunctionName")
|
||||
fun <K, V> WriteLockHashMap() =
|
||||
AsyncRWLockAbstractMap<K, V>(AsyncReadFirstRWLock())
|
@ -1,115 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncReadFirstRWLock
|
||||
|
||||
class AsyncLinkSlot<K, V> {
|
||||
private val lock = AsyncReadFirstRWLock()
|
||||
@Volatile
|
||||
private var node: Node<K, V>? = null
|
||||
@Volatile
|
||||
private var rSize = 0
|
||||
|
||||
val size: Int
|
||||
get() = rSize
|
||||
|
||||
suspend fun clear() {
|
||||
lock.doWrite {
|
||||
node = null
|
||||
rSize = 0
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun put(key: K, value: V) {
|
||||
node?.forEach {
|
||||
if (it.key == key) {
|
||||
it.value = value
|
||||
return
|
||||
}
|
||||
}
|
||||
lock.doWrite {
|
||||
node = Node(key, value, node)
|
||||
node?.prev = node
|
||||
rSize++
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun remove(key: K): V? {
|
||||
return lock doWrite@{
|
||||
node?.forEach {
|
||||
if (it.key == key) {
|
||||
if (it == node) {
|
||||
node = it.next
|
||||
it.next?.prev = null
|
||||
} else {
|
||||
it.prev?.next = it.next
|
||||
it.next?.prev = it.prev
|
||||
}
|
||||
rSize--
|
||||
return@doWrite it.value
|
||||
}
|
||||
}
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun containsKey(key: K): Boolean {
|
||||
return lock.doRead {
|
||||
node?.forEach {
|
||||
if (it.key == key) {
|
||||
return@doRead true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun containsValue(value: V): Boolean {
|
||||
return lock.doRead {
|
||||
node?.forEach {
|
||||
if (it.value == value) {
|
||||
return@doRead true
|
||||
}
|
||||
}
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun get(key: K): V? {
|
||||
return lock.doRead {
|
||||
node?.forEach {
|
||||
if (it.key == key) {
|
||||
return@doRead it.value
|
||||
}
|
||||
}
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
fun isEmpty(): Boolean {
|
||||
return node == null
|
||||
}
|
||||
|
||||
private data class Node<K, V>(
|
||||
val key: K,
|
||||
var value: V,
|
||||
var next: Node<K, V>?,
|
||||
var prev: Node<K, V>? = null
|
||||
) : Iterable<Node<K, V>> {
|
||||
override fun iterator(): Iterator<Node<K, V>> {
|
||||
return NodeIterator(this)
|
||||
}
|
||||
}
|
||||
|
||||
private class NodeIterator<K, V>(private var node: Node<K, V>?) : Iterator<Node<K, V>> {
|
||||
|
||||
override fun hasNext(): Boolean {
|
||||
return node != null
|
||||
}
|
||||
|
||||
override fun next(): Node<K, V> {
|
||||
val thisNode = node!!
|
||||
node = node?.next
|
||||
return thisNode
|
||||
}
|
||||
}
|
||||
}
|
@ -1,138 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async.collections
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncWriteFirstRWLock
|
||||
import cn.tursom.core.datastruct.ArrayMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncCollection
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncSet
|
||||
|
||||
class AsyncArrayMap<K : Comparable<K>, V> : AsyncPotableMap<K, V> {
|
||||
private val lock = AsyncWriteFirstRWLock()
|
||||
private val map = ArrayMap<K, V>()
|
||||
|
||||
override val size: Int get() = map.size
|
||||
override val entries: AsyncSet<Map.Entry<K, V>> = AsyncEntrySet(this)
|
||||
override val keys: AsyncSet<K> = AsyncKeySet(this)
|
||||
override val values: AsyncCollection<V> = AsyncValueCollection(this)
|
||||
|
||||
override suspend fun containsKey(key: K): Boolean {
|
||||
return lock.doRead { map.containsKey(key) }
|
||||
}
|
||||
|
||||
override suspend fun containsValue(value: V): Boolean {
|
||||
return lock.doRead { map.containsValue(value) }
|
||||
}
|
||||
|
||||
override suspend fun get(key: K): V? {
|
||||
return lock.doRead { map[key] }
|
||||
}
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return lock.doRead { map.isEmpty() }
|
||||
}
|
||||
|
||||
override suspend fun clear() {
|
||||
lock.doWrite { map.clear() }
|
||||
}
|
||||
|
||||
override suspend fun set(key: K, value: V): V? {
|
||||
return lock { map.setAndGet(key, value) }
|
||||
}
|
||||
|
||||
override suspend fun putIfAbsent(key: K, value: V): Boolean {
|
||||
return lock {
|
||||
if (containsKey(key)) false
|
||||
else {
|
||||
map.setAndGet(key, value)
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun putAll(from: Map<out K, V>) {
|
||||
return lock { map.putAll(from) }
|
||||
}
|
||||
|
||||
override suspend fun remove(key: K): V? {
|
||||
return lock { map.delete(key) }
|
||||
}
|
||||
|
||||
override suspend fun contains(element: Map.Entry<K, V>): Boolean {
|
||||
return get(element.key) == element.value
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<Map.Entry<K, V>>): Boolean {
|
||||
return elements.forEach { contains(it) }
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
return lock {
|
||||
map.forEach { !action(it) }
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class AsyncEntrySet<K : Comparable<K>, V>(private val map: AsyncArrayMap<K, V>) : AsyncSet<Map.Entry<K, V>> {
|
||||
override val size: Int
|
||||
get() = map.size
|
||||
|
||||
override suspend fun contains(element: Map.Entry<K, V>): Boolean {
|
||||
return map.get(element.key) == element.value
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<Map.Entry<K, V>>): Boolean {
|
||||
return elements.forEach { contains(it) }
|
||||
}
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return map.isEmpty()
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
return map.forEach(action)
|
||||
}
|
||||
}
|
||||
|
||||
class AsyncKeySet<K : Comparable<K>>(private val map: AsyncArrayMap<K, *>) : AsyncSet<K> {
|
||||
override val size: Int
|
||||
get() = map.size
|
||||
|
||||
override suspend fun contains(element: K): Boolean {
|
||||
return map.containsKey(element)
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<K>): Boolean {
|
||||
return elements.forEach { map.containsKey(it) }
|
||||
}
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return size == 0
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (K) -> Boolean): Boolean {
|
||||
return map.forEach { action(it.key) }
|
||||
}
|
||||
}
|
||||
|
||||
class AsyncValueCollection<V>(private val map: AsyncArrayMap<*, V>) : AsyncCollection<V> {
|
||||
override val size: Int
|
||||
get() = map.size
|
||||
|
||||
override suspend fun contains(element: V): Boolean {
|
||||
return map.containsValue(element)
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<V>): Boolean {
|
||||
return elements.forEach { !map.containsValue(it) }
|
||||
}
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return size == 0
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (V) -> Boolean): Boolean {
|
||||
return map.forEach { action(it.value) }
|
||||
}
|
||||
}
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async.collections
|
||||
|
||||
class AsyncArrayMapSet<K : Comparable<K>> : AsyncMapSet<K>(AsyncArrayMap())
|
@ -1,44 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async.collections
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncLock
|
||||
import cn.tursom.utils.asynclock.AsyncRWLock
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
|
||||
class AsyncLockAbstractMap<K, V>(
|
||||
override val lock: AsyncLock,
|
||||
override val map: java.util.AbstractMap<K, V> = HashMap()
|
||||
) : AsyncLockMap<K, V>(lock, map), AsyncPotableMap<K, V> {
|
||||
override suspend fun clear() {
|
||||
lock { map.clear() }
|
||||
}
|
||||
|
||||
override suspend fun putIfAbsent(key: K, value: V): Boolean {
|
||||
return lock {
|
||||
if (map.containsKey(key)) false
|
||||
else {
|
||||
map[key] = value
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun putAll(from: Map<out K, V>) {
|
||||
lock {
|
||||
map.putAll(from)
|
||||
}
|
||||
}
|
||||
|
||||
constructor(lock: AsyncRWLock) : this(lock, HashMap())
|
||||
|
||||
override suspend fun set(key: K, value: V): V? {
|
||||
return lock {
|
||||
map.put(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun remove(key: K): V? {
|
||||
return lock { map.remove(key) }
|
||||
}
|
||||
|
||||
override fun toString(): String = map.toString()
|
||||
}
|
@ -1,105 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async.collections
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncLock
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncCollection
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncSet
|
||||
|
||||
open class AsyncLockMap<K, V>(
|
||||
protected open val lock: AsyncLock,
|
||||
protected open val map: Map<K, V>
|
||||
) : AsyncMap<K, V> {
|
||||
override val size: Int get() = map.size
|
||||
override val entries: AsyncSet<Map.Entry<K, V>> = Entries()
|
||||
override val keys: AsyncSet<K> = Keys()
|
||||
override val values: AsyncCollection<V> = Values()
|
||||
|
||||
override suspend fun containsKey(key: K): Boolean {
|
||||
return lock { map.containsKey(key) }
|
||||
}
|
||||
|
||||
override suspend fun containsValue(value: V): Boolean {
|
||||
return lock { map.containsValue(value) }
|
||||
}
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return lock { map.isEmpty() }
|
||||
}
|
||||
|
||||
override suspend fun get(key: K): V? {
|
||||
return lock { map[key] }
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
return lock {
|
||||
map.forEach {
|
||||
if (!action(it)) return@lock false
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = map.toString()
|
||||
|
||||
inner class Entries : AsyncSet<Map.Entry<K, V>> {
|
||||
override val size: Int get() = this@AsyncLockMap.size
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return this@AsyncLockMap.isEmpty()
|
||||
}
|
||||
|
||||
override suspend fun contains(element: Map.Entry<K, V>): Boolean {
|
||||
return contains(element)
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<Map.Entry<K, V>>): Boolean {
|
||||
return containsAll(elements)
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
return this@AsyncLockMap.forEach { action(it) }
|
||||
}
|
||||
}
|
||||
|
||||
inner class Keys : AsyncSet<K> {
|
||||
override val size: Int
|
||||
get() = this@AsyncLockMap.size
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return this@AsyncLockMap.isEmpty()
|
||||
}
|
||||
|
||||
override suspend fun contains(element: K): Boolean {
|
||||
return containsKey(element)
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<K>): Boolean {
|
||||
return elements.forEach { containsKey(it) }
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (K) -> Boolean): Boolean {
|
||||
return this@AsyncLockMap.forEach { action(it.key) }
|
||||
}
|
||||
}
|
||||
|
||||
inner class Values : AsyncCollection<V> {
|
||||
override val size: Int
|
||||
get() = this@AsyncLockMap.size
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return this@AsyncLockMap.isEmpty()
|
||||
}
|
||||
|
||||
override suspend fun contains(element: V): Boolean {
|
||||
return containsValue(element)
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<V>): Boolean {
|
||||
return elements.forEach { containsValue(it) }
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (V) -> Boolean): Boolean {
|
||||
return this@AsyncLockMap.forEach { action(it.value) }
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async.collections
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncWriteFirstRWLock
|
||||
import cn.tursom.core.datastruct.SetMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncCollection
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableSet
|
||||
|
||||
open class AsyncMapSet<K>(private val map: AsyncPotableMap<K, Unit> = AsyncRWLockAbstractMap(AsyncWriteFirstRWLock())) : AsyncPotableSet<K> {
|
||||
override val size: Int get() = map.size
|
||||
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return size == 0
|
||||
}
|
||||
|
||||
override suspend fun contains(element: K): Boolean {
|
||||
return map.containsKey(element)
|
||||
}
|
||||
|
||||
override suspend fun containsAll(elements: AsyncCollection<K>): Boolean {
|
||||
return elements.forEach { map.containsKey(it) }
|
||||
}
|
||||
|
||||
override suspend fun clear(): AsyncPotableSet<K> {
|
||||
map.clear()
|
||||
return this
|
||||
}
|
||||
|
||||
override suspend fun put(key: K): AsyncPotableSet<K> {
|
||||
map.set(key, Unit)
|
||||
return this
|
||||
}
|
||||
|
||||
override suspend fun putIfAbsent(key: K): Boolean {
|
||||
return map.putIfAbsent(key, Unit)
|
||||
}
|
||||
|
||||
override suspend fun putAll(from: Set<K>): AsyncPotableSet<K> {
|
||||
map.putAll(SetMap(from))
|
||||
return this
|
||||
}
|
||||
|
||||
override suspend fun remove(key: K): AsyncPotableSet<K> {
|
||||
map.remove(key)
|
||||
return this
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (K) -> Boolean): Boolean {
|
||||
return map.forEach { action(it.key) }
|
||||
}
|
||||
}
|
||||
|
@ -1,45 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async.collections
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncRWLock
|
||||
import cn.tursom.core.datastruct.async.interfaces.AsyncPotableMap
|
||||
|
||||
class AsyncRWLockAbstractMap<K, V>(
|
||||
lock: AsyncRWLock,
|
||||
override val map: java.util.AbstractMap<K, V> = HashMap()
|
||||
) : AsyncRWLockMap<K, V>(lock, map), AsyncPotableMap<K, V> {
|
||||
constructor(lock: AsyncRWLock) : this(lock, HashMap())
|
||||
|
||||
override suspend fun set(key: K, value: V): V? {
|
||||
return lock.doWrite {
|
||||
map.put(key, value)
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun remove(key: K): V? {
|
||||
return lock.doWrite { map.remove(key) }
|
||||
}
|
||||
|
||||
override suspend fun clear() {
|
||||
lock { map.clear() }
|
||||
}
|
||||
|
||||
override suspend fun putIfAbsent(key: K, value: V): Boolean {
|
||||
return lock {
|
||||
if (map.containsKey(key)) false
|
||||
else {
|
||||
map[key] = value
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun putAll(from: Map<out K, V>) {
|
||||
lock {
|
||||
from.forEach { (k, u) ->
|
||||
map[k] = u
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun toString(): String = map.toString()
|
||||
}
|
@ -1,37 +0,0 @@
|
||||
package cn.tursom.utils.datastruct.async.collections
|
||||
|
||||
import cn.tursom.utils.asynclock.AsyncRWLock
|
||||
|
||||
open class AsyncRWLockMap<K, V>(
|
||||
override val lock: AsyncRWLock,
|
||||
map: Map<K, V>
|
||||
) : AsyncLockMap<K, V>(lock, map) {
|
||||
override suspend fun isEmpty(): Boolean {
|
||||
return lock.doRead { map.isEmpty() }
|
||||
}
|
||||
|
||||
override suspend fun isNotEmpty(): Boolean {
|
||||
return lock.doRead { map.isNotEmpty() }
|
||||
}
|
||||
|
||||
override suspend fun get(key: K): V? {
|
||||
return lock.doRead { map[key] }
|
||||
}
|
||||
|
||||
override suspend fun containsKey(key: K): Boolean {
|
||||
return lock.doRead { map.containsKey(key) }
|
||||
}
|
||||
|
||||
override suspend fun containsValue(value: V): Boolean {
|
||||
return lock.doRead { map.containsValue(value) }
|
||||
}
|
||||
|
||||
override suspend fun forEach(action: suspend (Map.Entry<K, V>) -> Boolean): Boolean {
|
||||
return lock.doRead {
|
||||
map.forEach {
|
||||
if (!action(it)) return@doRead false
|
||||
}
|
||||
true
|
||||
}
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package cn.tursom.utils.storage
|
||||
|
||||
import cn.tursom.core.storage.StorageHandler
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.delay
|
||||
import kotlinx.coroutines.launch
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class AsyncBufferedStorageHandler<T>(
|
||||
// 最小缓冲时间
|
||||
private val minBufTime: Long = 500,
|
||||
private val singleThreadWrite: Boolean = true,
|
||||
// 数据批量写入处理器
|
||||
private val writeHandler: suspend (list: Collection<T>) -> Unit
|
||||
) : StorageHandler<T> {
|
||||
private val onWrite = AtomicBoolean(false)
|
||||
|
||||
@Volatile
|
||||
private var msgList = ConcurrentLinkedQueue<T>()
|
||||
|
||||
private val write = object {
|
||||
suspend operator fun invoke() {
|
||||
val list = msgList
|
||||
delay(minBufTime)
|
||||
msgList = ConcurrentLinkedQueue()
|
||||
// 可能还有未释放 msgList 对象的线程,要稍微等待一下
|
||||
delay(1)
|
||||
if (singleThreadWrite) {
|
||||
try {
|
||||
writeHandler(list)
|
||||
} finally {
|
||||
if (msgList.isNotEmpty()) {
|
||||
val write = this
|
||||
GlobalScope.launch { write() }
|
||||
} else {
|
||||
onWrite.set(false)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
onWrite.set(false)
|
||||
writeHandler(list)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 向缓冲中添加一个写入对象
|
||||
*/
|
||||
override fun add(obj: T) {
|
||||
msgList.add(obj)
|
||||
if (onWrite.compareAndSet(false, true)) {
|
||||
GlobalScope.launch {
|
||||
write()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1 +0,0 @@
|
||||
cn.tursom.utils.coroutine.MainDispatcherFactory
|
@ -1,62 +0,0 @@
|
||||
package cn.tursom.utils.coroutine
|
||||
|
||||
import kotlinx.coroutines.*
|
||||
import kotlin.coroutines.ContinuationInterceptor
|
||||
import kotlin.coroutines.coroutineContext
|
||||
|
||||
val testCoroutineLocal = CoroutineLocal<Int>()
|
||||
|
||||
suspend fun testCustomContext() {
|
||||
testCoroutineLocal.set(1)
|
||||
testInlineCustomContext()
|
||||
}
|
||||
|
||||
suspend fun testInlineCustomContext() {
|
||||
println(coroutineContext)
|
||||
println("===================")
|
||||
}
|
||||
|
||||
annotation class Request(val url: String, val method: String = "GET")
|
||||
|
||||
interface CoroutineLocalTest {
|
||||
@Request("http://tursom.cn:15015/living")
|
||||
suspend fun test(): String
|
||||
}
|
||||
|
||||
class Test : CoroutineScope by MainScope() {
|
||||
suspend fun test() {
|
||||
testCoroutineLocal.set(1)
|
||||
println(coroutineContext)
|
||||
coroutineScope {
|
||||
println(coroutineContext)
|
||||
delay(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
object R : () -> R {
|
||||
override fun invoke(): R = this
|
||||
}
|
||||
|
||||
val threadLocal = ThreadLocal<String>()
|
||||
|
||||
fun main() = runBlocking {
|
||||
println(coroutineContext[ContinuationInterceptor])
|
||||
MainDispatcher.init()
|
||||
runOnUiThread(threadLocal.asContextElement()) {
|
||||
threadLocal.set("hello")
|
||||
//Test().test()
|
||||
//println(testCoroutineLocal.get())
|
||||
println(threadLocal.get())
|
||||
println(coroutineContext)
|
||||
launch(Dispatchers.Main) {
|
||||
println(threadLocal.get())
|
||||
println(coroutineContext)
|
||||
}
|
||||
//runOnUiThread {
|
||||
// println(coroutineContext)
|
||||
// println(testCoroutineLocal.get())
|
||||
//}
|
||||
}
|
||||
MainDispatcher.close()
|
||||
}
|
Loading…
Reference in New Issue
Block a user