mirror of
https://github.com/tursom/TursomServer.git
synced 2025-03-25 17:10:07 +08:00
update
This commit is contained in:
parent
d45dae40d5
commit
6ba77ec7b7
@ -13,7 +13,10 @@ include("ts-core:ts-coroutine")
|
||||
include("ts-core:ts-coroutine:ts-coroutine-lock")
|
||||
include("ts-core:ts-ws-client")
|
||||
include("ts-core:ts-yaml")
|
||||
include("ts-core:ts-json")
|
||||
include("ts-socket")
|
||||
include("ts-web")
|
||||
include("ts-web:ts-web-netty")
|
||||
//include("web", "aop", "database", "utils", "utils:xml", "utils:async-http", "web:netty-web")
|
||||
//include("socket", "socket:socket-async")
|
||||
//include("AsyncSocket")
|
||||
|
@ -6,6 +6,7 @@ plugins {
|
||||
dependencies {
|
||||
api(project(":"))
|
||||
compileOnly(group = "com.google.code.gson", name = "gson", version = "2.8.6")
|
||||
compileOnly(group = "io.netty", name = "netty-all", version = "4.1.43.Final")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
|
@ -1,4 +1,4 @@
|
||||
package cn.tursom.ws
|
||||
package cn.tursom.core.ws
|
||||
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.Unpooled
|
34
ts-core/ts-json/build.gradle.kts
Normal file
34
ts-core/ts-json/build.gradle.kts
Normal file
@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":"))
|
||||
compileOnly(group = "com.google.code.gson", name = "gson", version = "2.8.6")
|
||||
compileOnly(group = "com.fasterxml.jackson.core", name = "jackson-core", version = "2.10.1")
|
||||
compileOnly(group = "com.fasterxml.jackson.core", name = "jackson-databind", version = "2.10.1")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks)
|
||||
|
||||
tasks.register("install") {
|
||||
finalizedBy(tasks["publishToMavenLocal"])
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
groupId = project.group.toString()
|
||||
artifactId = project.name
|
||||
version = project.version.toString()
|
||||
|
||||
from(components["java"])
|
||||
try {
|
||||
artifact(tasks["sourcesJar"])
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
package cn.tursom.utils.json
|
||||
package cn.tursom.core.json
|
||||
|
||||
import com.sun.org.apache.xalan.internal.lib.ExsltMath.power
|
||||
import java.lang.RuntimeException
|
||||
|
||||
object Json {
|
||||
class JsonFormatException(message: String? = null) : RuntimeException(message) {
|
@ -0,0 +1,6 @@
|
||||
package cn.tursom.core.json
|
||||
|
||||
interface JsonWorker {
|
||||
fun toJson(obj: Any): String?
|
||||
fun <T> fromJson(json: String, clazz: Class<T>): T?
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
package cn.tursom.core.json
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper
|
||||
import com.google.gson.Gson
|
||||
|
||||
class JsonWorkerImpl : JsonWorker {
|
||||
companion object {
|
||||
private val gson = try {
|
||||
Gson()
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
|
||||
private val jackson = try {
|
||||
ObjectMapper()
|
||||
} catch (e: Throwable) {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
override fun toJson(obj: Any): String? = gson?.toJson(obj) ?: jackson?.writeValueAsString(obj)
|
||||
|
||||
override fun <T> fromJson(json: String, clazz: Class<T>): T? =
|
||||
gson?.fromJson(json, clazz) ?: jackson?.readValue(json, clazz)
|
||||
|
||||
override fun toString(): String {
|
||||
return "JsonWorkerImpl(gson=$gson, jackson=$jackson)"
|
||||
}
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
package cn.tursom.ws
|
||||
package cn.tursom.core.ws
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
@ -1,4 +1,4 @@
|
||||
package cn.tursom.ws
|
||||
package cn.tursom.core.ws
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.channel.SimpleChannelInboundHandler
|
@ -1,4 +1,4 @@
|
||||
package cn.tursom.ws
|
||||
package cn.tursom.core.ws
|
||||
|
||||
import io.netty.channel.ChannelHandlerContext
|
||||
import io.netty.channel.ChannelPromise
|
@ -1,4 +1,4 @@
|
||||
package cn.tursom.ws
|
||||
package cn.tursom.core.ws
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
35
ts-web/build.gradle.kts
Normal file
35
ts-web/build.gradle.kts
Normal file
@ -0,0 +1,35 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":ts-core"))
|
||||
api(project(":ts-core:ts-buffer"))
|
||||
api(project(":ts-core:ts-datastruct"))
|
||||
compileOnly(project(":ts-core:ts-json"))
|
||||
api(group = "org.slf4j", name = "slf4j-api", version = "1.7.29")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks)
|
||||
|
||||
tasks.register("install") {
|
||||
finalizedBy(tasks["publishToMavenLocal"])
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
groupId = project.group.toString()
|
||||
artifactId = project.name
|
||||
version = project.version.toString()
|
||||
|
||||
from(components["java"])
|
||||
try {
|
||||
artifact(tasks["sourcesJar"])
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,9 +1,9 @@
|
||||
package cn.tursom.web.router
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.json.JsonWorkerImpl
|
||||
import cn.tursom.core.lambda
|
||||
import cn.tursom.core.regex.regex
|
||||
import cn.tursom.json.JsonWorkerImpl
|
||||
import cn.tursom.web.ExceptionContent
|
||||
import cn.tursom.web.HttpContent
|
||||
import cn.tursom.web.HttpHandler
|
||||
@ -14,7 +14,10 @@ import cn.tursom.web.router.impl.SimpleRouter
|
||||
import cn.tursom.web.utils.Chunked
|
||||
import cn.tursom.web.utils.ContextTypeEnum
|
||||
import org.slf4j.LoggerFactory
|
||||
import java.io.*
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.PrintStream
|
||||
import java.io.RandomAccessFile
|
||||
import java.lang.reflect.Method
|
||||
import java.util.concurrent.LinkedBlockingQueue
|
||||
import java.util.concurrent.ThreadFactory
|
@ -3,7 +3,6 @@ package cn.tursom.web.router.impl
|
||||
import cn.tursom.web.router.Router
|
||||
import java.util.*
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.concurrent.read
|
||||
import kotlin.concurrent.write
|
||||
|
||||
@ -14,7 +13,8 @@ class FilterRouter<T>(
|
||||
val slashOnceMore = Regex("/+")
|
||||
}
|
||||
|
||||
private val flower = Regex("\\${matchPair.first}[^\\${matchPair.first}\\${matchPair.second}]*\\${matchPair.second}")
|
||||
private val flower =
|
||||
Regex("\\\\${matchPair.first}[^\\\\${matchPair.first}\\\\${matchPair.second}]*\\\\${matchPair.second}")
|
||||
private val lock = ReentrantReadWriteLock()
|
||||
private val routeList = ArrayList<RouteContext<T>>()
|
||||
|
@ -2,7 +2,6 @@ package cn.tursom.web.utils
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.web.HttpContent
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.File
|
||||
import java.io.RandomAccessFile
|
||||
import java.net.InetSocketAddress
|
34
ts-web/ts-web-netty/build.gradle.kts
Normal file
34
ts-web/ts-web-netty/build.gradle.kts
Normal file
@ -0,0 +1,34 @@
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
dependencies {
|
||||
api(project(":ts-core"))
|
||||
api(project(":ts-core:ts-log"))
|
||||
api(project(":ts-web"))
|
||||
api(group = "io.netty", name = "netty-all", version = "4.1.43.Final")
|
||||
}
|
||||
|
||||
@kotlin.Suppress("UNCHECKED_CAST")
|
||||
(rootProject.ext["excludeTest"] as (Project, TaskContainer) -> Unit)(project, tasks)
|
||||
|
||||
tasks.register("install") {
|
||||
finalizedBy(tasks["publishToMavenLocal"])
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
create<MavenPublication>("maven") {
|
||||
groupId = project.group.toString()
|
||||
artifactId = project.name
|
||||
version = project.version.toString()
|
||||
|
||||
from(components["java"])
|
||||
try {
|
||||
artifact(tasks["sourcesJar"])
|
||||
} catch (e: Exception) {
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -5,7 +5,6 @@ package cn.tursom.web.netty
|
||||
import io.netty.handler.codec.DateFormatter
|
||||
import io.netty.handler.codec.http.cookie.ServerCookieDecoder
|
||||
import java.util.*
|
||||
import kotlin.collections.HashMap
|
||||
|
||||
|
||||
fun parseHttpDate(date: CharSequence, start: Int = 0, end: Int = date.length): Date = DateFormatter.parseHttpDate(date, start, end)
|
@ -1,8 +1,8 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
||||
import cn.tursom.log.traceEnabled
|
||||
import cn.tursom.utils.bytebuffer.NettyByteBuffer
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.ByteBufAllocator
|
||||
import io.netty.buffer.Unpooled
|
@ -1,7 +1,7 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
||||
import cn.tursom.log.traceEnabled
|
||||
import cn.tursom.utils.bytebuffer.NettyByteBuffer
|
||||
import cn.tursom.web.utils.Chunked
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.ByteBufAllocator
|
@ -1,8 +1,8 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
||||
import cn.tursom.log.traceEnabled
|
||||
import cn.tursom.utils.bytebuffer.NettyByteBuffer
|
||||
import cn.tursom.web.ExceptionContent
|
||||
import io.netty.buffer.ByteBuf
|
||||
import io.netty.buffer.CompositeByteBuf
|
@ -1,8 +1,8 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
||||
import cn.tursom.log.traceEnabled
|
||||
import cn.tursom.utils.bytebuffer.NettyByteBuffer
|
||||
import cn.tursom.web.MutableHttpContent
|
||||
import cn.tursom.web.utils.Chunked
|
||||
import io.netty.buffer.ByteBuf
|
@ -1,6 +1,6 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import cn.tursom.utils.WebSocketFrameWrapper
|
||||
import cn.tursom.core.ws.WebSocketFrameWrapper
|
||||
import cn.tursom.web.HttpHandler
|
||||
import cn.tursom.web.HttpServer
|
||||
import cn.tursom.web.WebSocketHandler
|
@ -1,9 +1,9 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import cn.tursom.core.buffer.ByteBuffer
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
||||
import cn.tursom.core.buffer.read
|
||||
import cn.tursom.log.traceEnabled
|
||||
import cn.tursom.utils.bytebuffer.NettyByteBuffer
|
||||
import cn.tursom.web.WebSocketContent
|
||||
import io.netty.buffer.Unpooled
|
||||
import io.netty.channel.Channel
|
@ -1,6 +1,6 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import cn.tursom.utils.bytebuffer.NettyByteBuffer
|
||||
import cn.tursom.core.buffer.impl.NettyByteBuffer
|
||||
import cn.tursom.web.WebSocketHandler
|
||||
import io.netty.channel.Channel
|
||||
import io.netty.channel.ChannelHandlerContext
|
@ -1,10 +1,11 @@
|
||||
package cn.tursom.web.netty
|
||||
|
||||
import io.netty.handler.codec.http.*
|
||||
import io.netty.handler.codec.http.HttpContent
|
||||
import io.netty.handler.codec.http.HttpMethod
|
||||
import io.netty.handler.codec.http.HttpRequest
|
||||
import io.netty.handler.codec.http.QueryStringDecoder
|
||||
import io.netty.handler.codec.http.multipart.Attribute
|
||||
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
import kotlin.collections.set
|
||||
|
||||
/**
|
@ -1,33 +0,0 @@
|
||||
package cn.tursom.math
|
||||
|
||||
import kotlin.math.PI
|
||||
import kotlin.math.cos
|
||||
import kotlin.math.sin
|
||||
|
||||
fun fft1(a: Array<Complex>): Array<Complex> {
|
||||
if (a.size == 1) return a
|
||||
val a0 = Array(a.size shr 1) {
|
||||
a[it shl 1]
|
||||
}
|
||||
val a1 = Array(a.size shr 1) {
|
||||
a[(it shl 1) + 1]
|
||||
}
|
||||
fft1(a0)
|
||||
fft1(a1)
|
||||
val wn = Complex(cos(2 * PI / a.size), sin(2 * PI / a.size))
|
||||
val w = Complex(1.0, 0.0)
|
||||
repeat(a.size shr 1) { k ->
|
||||
a[k] = a0[k] + w * a1[k]
|
||||
a[k + (a.size shr 1)] = a0[k] - w * a1[k]
|
||||
w.plusAssign(wn)
|
||||
}
|
||||
return a
|
||||
}
|
||||
|
||||
fun main() {
|
||||
val source = Array(8) {
|
||||
Complex(sin(it.toDouble()))
|
||||
}
|
||||
println(source.asList())
|
||||
println(fft1(source).asList())
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
dependencies {
|
||||
compile project(":")
|
||||
}
|
@ -1,55 +0,0 @@
|
||||
package cn.tursom.test
|
||||
|
||||
import java.util.concurrent.CountDownLatch
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import kotlin.concurrent.thread
|
||||
|
||||
class PerformanceTest(
|
||||
val countPerThread: Int,
|
||||
val threadCount: Int = 1,
|
||||
val handler: PerformanceTestHandler
|
||||
) {
|
||||
val totalCount = countPerThread * threadCount
|
||||
|
||||
constructor(
|
||||
countPerThread: Int,
|
||||
threadCount: Int = 1,
|
||||
handler: () -> Unit
|
||||
) : this(countPerThread, threadCount, object : PerformanceTestHandler, () -> Unit by handler {})
|
||||
|
||||
fun run(): TestResult {
|
||||
val schedule = AtomicInteger(0)
|
||||
val wait = CountDownLatch(threadCount)
|
||||
val runLock = CountDownLatch(1)
|
||||
var line95 = 0L
|
||||
var line98 = 0L
|
||||
var line99 = 0L
|
||||
repeat(threadCount) {
|
||||
thread {
|
||||
runLock.await()
|
||||
try {
|
||||
repeat(countPerThread) {
|
||||
val loop = schedule.getAndIncrement()
|
||||
if (loop * 100 % totalCount == 0) {
|
||||
val line = loop * 100 / totalCount
|
||||
when (line) {
|
||||
95 -> line95 = System.currentTimeMillis()
|
||||
98 -> line98 = System.currentTimeMillis()
|
||||
99 -> line99 = System.currentTimeMillis()
|
||||
}
|
||||
handler.logSchedule(line)
|
||||
}
|
||||
handler()
|
||||
}
|
||||
} finally {
|
||||
wait.countDown()
|
||||
}
|
||||
}
|
||||
}
|
||||
val start = System.currentTimeMillis()
|
||||
runLock.countDown()
|
||||
wait.await()
|
||||
val end = System.currentTimeMillis()
|
||||
return TestResult(start, end, line95, line98, line99)
|
||||
}
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
package cn.tursom.test
|
||||
|
||||
interface PerformanceTestHandler : () -> Unit {
|
||||
fun logSchedule(percentage: Int) {
|
||||
}
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
package cn.tursom.test
|
||||
|
||||
import java.util.concurrent.TimeUnit
|
||||
|
||||
data class TestResult(
|
||||
val startTime: Long,
|
||||
val endTime: Long,
|
||||
val line95: Long,
|
||||
val line98: Long,
|
||||
val line99: Long,
|
||||
val usingTime: Long = endTime - startTime,
|
||||
val usingTimeS: Long = TimeUnit.SECONDS.convert(usingTime, TimeUnit.MILLISECONDS),
|
||||
val t95: Long = line95 - startTime,
|
||||
val t98: Long = line98 - startTime,
|
||||
val t99: Long = line99 - startTime,
|
||||
val t95s: Long = TimeUnit.SECONDS.convert(t95, TimeUnit.MILLISECONDS),
|
||||
val t98s: Long = TimeUnit.SECONDS.convert(t98, TimeUnit.MILLISECONDS),
|
||||
val t99s: Long = TimeUnit.SECONDS.convert(t99, TimeUnit.MILLISECONDS)
|
||||
) {
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
package cn.tursom.utils.asynclock
|
||||
|
||||
import kotlinx.coroutines.delay
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
interface AsyncLock {
|
||||
suspend fun sync(block: suspend () -> Unit)
|
||||
suspend fun isLock(): Boolean
|
||||
suspend operator fun <T> invoke(block: suspend () -> T): T
|
||||
|
||||
suspend fun AtomicBoolean.lock(delayTime: Long) {
|
||||
// 如果得不到锁,先自旋20次
|
||||
var maxLoopTime = 20
|
||||
while (maxLoopTime-- > 0) {
|
||||
if (compareAndSet(false, true)) return
|
||||
}
|
||||
while (!compareAndSet(false, true)) {
|
||||
delay(delayTime)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun AtomicBoolean.release() {
|
||||
set(false)
|
||||
}
|
||||
|
||||
suspend fun AtomicBoolean.wait(delayTime: Long) {
|
||||
// 如果得不到锁,先自旋20次
|
||||
var maxLoopTime = 20
|
||||
while (maxLoopTime-- > 0) {
|
||||
if (!get()) return
|
||||
}
|
||||
while (get()) {
|
||||
delay(delayTime)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun AsyncLock.wait(delayTime: Long) {
|
||||
// 如果得不到锁,先自旋20次
|
||||
var maxLoopTime = 20
|
||||
while (maxLoopTime-- > 0) {
|
||||
if (!isLock()) return
|
||||
}
|
||||
while (isLock()) {
|
||||
delay(delayTime)
|
||||
}
|
||||
}
|
||||
|
||||
suspend fun AtomicInteger.wait(delayTime: Long) {
|
||||
// 如果得不到锁,先自旋20次
|
||||
var maxLoopTime = 20
|
||||
while (maxLoopTime-- > 0) {
|
||||
if (get() <= 0) return
|
||||
}
|
||||
while (get() > 0) {
|
||||
delay(delayTime)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,22 +0,0 @@
|
||||
package cn.tursom.utils.asynclock
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class AsyncLoopLock : AsyncLock {
|
||||
private val lock = AtomicBoolean(false)
|
||||
|
||||
override suspend fun sync(block: suspend () -> Unit) {
|
||||
invoke(block)
|
||||
}
|
||||
|
||||
override suspend fun isLock(): Boolean = lock.get()
|
||||
|
||||
override suspend fun <T> invoke(block: suspend () -> T): T {
|
||||
while (!lock.compareAndSet(false, true));
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
lock.set(false)
|
||||
}
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
package cn.tursom.utils.asynclock
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
class AsyncMutexLock : AsyncLock {
|
||||
private val lock = AtomicBoolean(false)
|
||||
private val waitList = AsyncWaitList()
|
||||
|
||||
suspend fun wait() {
|
||||
var loopTime = 20
|
||||
while (loopTime-- > 0) if (!lock.get()) return
|
||||
waitList.wait()
|
||||
waitList.resume()
|
||||
}
|
||||
|
||||
override suspend fun sync(block: suspend () -> Unit) {
|
||||
invoke(block)
|
||||
}
|
||||
|
||||
override suspend fun isLock(): Boolean {
|
||||
return lock.get()
|
||||
}
|
||||
|
||||
override suspend operator fun <T> invoke(block: suspend () -> T): T {
|
||||
lock.lock()
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
lock.release()
|
||||
}
|
||||
}
|
||||
|
||||
private suspend fun AtomicBoolean.lock() {
|
||||
var loopTime = 20
|
||||
while (loopTime-- > 0) if (compareAndSet(false, true)) return
|
||||
waitList.wait()
|
||||
}
|
||||
|
||||
override suspend fun AtomicBoolean.release() {
|
||||
if (waitList.notEmpty) {
|
||||
waitList.resume()
|
||||
} else {
|
||||
set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +0,0 @@
|
||||
package cn.tursom.utils.asynclock
|
||||
|
||||
interface AsyncRWLock : AsyncLock {
|
||||
suspend fun <T> doRead(block: suspend () -> T): T
|
||||
suspend fun <T> doWrite(block: suspend () -> T): T
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package cn.tursom.utils.asynclock
|
||||
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
/**
|
||||
* 读优化锁
|
||||
*/
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
class AsyncReadFirstRWLock() : AsyncRWLock {
|
||||
private val lock = AsyncMutexLock()
|
||||
private val readNumber = AtomicInteger(0)
|
||||
private val writeList = AsyncWaitList()
|
||||
|
||||
override suspend fun <T> doRead(block: suspend () -> T): T {
|
||||
readNumber.incrementAndGet()
|
||||
lock.wait()
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
readNumber.decrementAndGet()
|
||||
if (readNumber.get() == 0) writeList.resume()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun <T> doWrite(block: suspend () -> T): T {
|
||||
return invoke(block)
|
||||
}
|
||||
|
||||
override suspend fun sync(block: suspend () -> Unit) {
|
||||
invoke(block)
|
||||
}
|
||||
|
||||
override suspend fun <T> invoke(block: suspend () -> T): T {
|
||||
while (readNumber.get() != 0) writeList.wait()
|
||||
return lock { block() }
|
||||
}
|
||||
|
||||
override suspend fun isLock(): Boolean {
|
||||
return lock.isLock()
|
||||
}
|
||||
}
|
@ -1,58 +0,0 @@
|
||||
package cn.tursom.utils.asynclock
|
||||
|
||||
import cn.tursom.core.Unsafe.unsafe
|
||||
import java.io.Closeable
|
||||
import kotlin.coroutines.Continuation
|
||||
import kotlin.coroutines.resume
|
||||
import kotlin.coroutines.suspendCoroutine
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
class AsyncWaitList : Closeable {
|
||||
val empty: Boolean get() = lockList == null
|
||||
val notEmpty: Boolean get() = lockList != null
|
||||
|
||||
suspend fun wait() = suspendCoroutine<Int> { cont ->
|
||||
var list = lockList
|
||||
while (!unsafe.compareAndSwapObject(this, listOffset, list, LockNode(cont, list))) {
|
||||
list = lockList
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun resume(): Boolean {
|
||||
var list = lockList ?: return false
|
||||
while (!unsafe.compareAndSwapObject(this, listOffset, list, list.next)) {
|
||||
list = lockList ?: return false
|
||||
}
|
||||
list.cont.resume(0)
|
||||
return true
|
||||
}
|
||||
|
||||
fun resumeAll(): Boolean {
|
||||
var list: LockNode? = lockList ?: return false
|
||||
while (!unsafe.compareAndSwapObject(this, listOffset, list, null)) {
|
||||
list = lockList ?: return false
|
||||
}
|
||||
while (list != null) {
|
||||
list.cont.resume(0)
|
||||
list = list.next
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
resumeAll()
|
||||
}
|
||||
|
||||
@Volatile
|
||||
private var lockList: LockNode? = null
|
||||
//private val listLock = AsyncLoopLock()
|
||||
|
||||
private data class LockNode(val cont: Continuation<Int>, val next: LockNode? = null)
|
||||
|
||||
companion object {
|
||||
val listOffset = run {
|
||||
unsafe.objectFieldOffset(AsyncWaitList::class.java.getDeclaredField("lockList"))
|
||||
}
|
||||
}
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
package cn.tursom.utils.asynclock
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate")
|
||||
class AsyncWriteFirstRWLock(val delayTime: Long = 10) : AsyncRWLock {
|
||||
|
||||
private val lock = AtomicBoolean(false)
|
||||
private val readNumber = AtomicInteger(0)
|
||||
private val writeNumber = AtomicInteger(0)
|
||||
|
||||
override suspend fun <T> doWrite(block: suspend () -> T): T {
|
||||
return invoke(block)
|
||||
}
|
||||
|
||||
override suspend fun <T> doRead(block: suspend () -> T): T {
|
||||
// 先等待通知锁关闭
|
||||
writeNumber.wait(delayTime)
|
||||
|
||||
// 添加读计数
|
||||
readNumber.incrementAndGet()
|
||||
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
// 减少读计数
|
||||
readNumber.decrementAndGet()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun sync(block: suspend () -> Unit) {
|
||||
invoke(block)
|
||||
}
|
||||
|
||||
override suspend fun <T> invoke(block: suspend () -> T): T {
|
||||
writeNumber.incrementAndGet()
|
||||
|
||||
repeat(20) {}
|
||||
|
||||
readNumber.wait(delayTime)
|
||||
|
||||
lock.lock(delayTime)
|
||||
|
||||
try {
|
||||
return block()
|
||||
} finally {
|
||||
lock.release()
|
||||
writeNumber.decrementAndGet()
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun isLock(): Boolean {
|
||||
return lock.get()
|
||||
}
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
dependencies {
|
||||
compile project(":")
|
||||
// 解析YAML
|
||||
implementation group: 'org.yaml', name: 'snakeyaml', version: '1.25'
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
package cn.tursom.yaml
|
||||
|
||||
import cn.tursom.core.Parser
|
||||
import cn.tursom.core.ThreadLocalSimpleDateFormat
|
||||
import cn.tursom.core.getClazz
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
import java.lang.reflect.Modifier
|
||||
import java.util.*
|
||||
|
||||
|
||||
@Suppress("MemberVisibilityCanBePrivate", "unused")
|
||||
object Yaml {
|
||||
private val simpleDateFormat = ThreadLocalSimpleDateFormat()
|
||||
private val yaml = Yaml()
|
||||
|
||||
fun toYaml(obj: Any): String {
|
||||
val stringBuilder = StringBuilder()
|
||||
toYaml(obj, stringBuilder, "")
|
||||
return stringBuilder.toString()
|
||||
}
|
||||
|
||||
private fun toYaml(obj: Any, stringBuilder: StringBuilder, indentation: String, inCollection: Boolean = false) {
|
||||
when (obj) {
|
||||
is Byte -> stringBuilder.append(obj)
|
||||
is Char -> stringBuilder.append(obj)
|
||||
is Short -> stringBuilder.append(obj)
|
||||
is Int -> stringBuilder.append(obj)
|
||||
is Long -> stringBuilder.append(obj)
|
||||
is Float -> stringBuilder.append(obj)
|
||||
is Double -> stringBuilder.append(obj)
|
||||
is Date -> stringBuilder.append(simpleDateFormat.get().format(obj))
|
||||
is String -> when {
|
||||
obj.contains('\n') -> {
|
||||
stringBuilder.append("|${if (obj.endsWith('\n')) '+' else '-'}")
|
||||
obj.split('\n').forEach {
|
||||
stringBuilder.append("$indentation$it")
|
||||
}
|
||||
}
|
||||
obj.startsWith('|') -> stringBuilder.append("\"$obj\"")
|
||||
else -> {
|
||||
stringBuilder.append(obj)
|
||||
}
|
||||
}
|
||||
is Map<*, *> -> {
|
||||
var first = true
|
||||
obj.forEach { (any, u) ->
|
||||
if (inCollection && first) {
|
||||
stringBuilder.append("${any ?: return@forEach}: ")
|
||||
first = false
|
||||
} else {
|
||||
stringBuilder.append("$indentation${any ?: return@forEach}: ")
|
||||
}
|
||||
toYaml(u ?: return@forEach, stringBuilder, "$indentation ")
|
||||
if (!stringBuilder.endsWith('\n')) {
|
||||
stringBuilder.append("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
is Collection<*> -> if (obj.isEmpty()) {
|
||||
stringBuilder.append("[]")
|
||||
} else {
|
||||
var appended = 0
|
||||
obj.forEach {
|
||||
it ?: return@forEach
|
||||
stringBuilder.append("${if (appended == 0) "\n" else ""}$indentation- ")
|
||||
appended++
|
||||
toYaml(it, stringBuilder, "$indentation ", true)
|
||||
if (!stringBuilder.endsWith('\n')) {
|
||||
stringBuilder.append("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
else -> {
|
||||
var first = true
|
||||
fun getIndentation() = if (inCollection && first) {
|
||||
first = false
|
||||
""
|
||||
} else {
|
||||
indentation
|
||||
}
|
||||
obj.javaClass.declaredFields.forEach {
|
||||
if ((it.modifiers and (Modifier.STATIC or Modifier.TRANSIENT)) != 0) return@forEach
|
||||
it.isAccessible = true
|
||||
val value = it.get(obj)
|
||||
stringBuilder.append("${getIndentation()}${it.name}: ")
|
||||
toYaml(value, stringBuilder, "${getIndentation()} ")
|
||||
if (!stringBuilder.endsWith('\n')) {
|
||||
stringBuilder.append("\n")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline fun <reified T> parse(yaml: Any) = Parser.parse(yaml, T::class.java)
|
||||
inline fun <reified T> parse(yaml: String) = parse(yaml, T::class.java)
|
||||
inline fun <reified T> parseResource(path: String) = parseResource(path, T::class.java)
|
||||
inline fun <reified T> parseResource(classLoader: ClassLoader, path: String) = parseResource(classLoader, path, T::class.java)
|
||||
|
||||
fun <T> parseResource(path: String, clazz: Class<T>) = parseResource(this.javaClass.classLoader, path, clazz)
|
||||
fun <T> parseResource(classLoader: ClassLoader, path: String, clazz: Class<T>) = Parser.parse(yaml.load(classLoader.getResourceAsStream(path)), clazz)
|
||||
fun <T> parse(yaml: String, clazz: Class<T>) = Parser.parse(this.yaml.load(yaml), clazz)
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
dependencies {
|
||||
compile project(":")
|
||||
api project(":json")
|
||||
api group: 'org.slf4j', name: 'slf4j-api', version: '1.7.29'
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
dependencies {
|
||||
//compile project(":")
|
||||
compile project(":web")
|
||||
implementation project(":utils")
|
||||
api project(":log")
|
||||
compile group: "io.netty", name: "netty-all", version: "4.1.43.Final"
|
||||
}
|
Loading…
Reference in New Issue
Block a user