Kotlin coroutine

This commit is contained in:
Him188moe 2019-09-22 20:04:43 +08:00
parent b10e0104ae
commit 2b02121b66
6 changed files with 53 additions and 38 deletions

View File

@ -23,7 +23,7 @@ abstract class Contact internal constructor(val bot: Bot, val number: Long) {
/**
* 上传图片
*/
suspend fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture<Unit> {
fun uploadImage(session: LoginSession, image: UnsolvedImage): CompletableFuture<Unit> {
return image.upload(session, this)
}

View File

@ -1,5 +1,6 @@
package net.mamoe.mirai.event
import kotlinx.coroutines.runBlocking
import java.util.function.Consumer
import java.util.function.Predicate
@ -7,12 +8,20 @@ import java.util.function.Predicate
* @author Him188moe
*/
class MiraiEventHookKt<E : MiraiEvent>(eventClass: Class<E>) : MiraiEventHook<E>(eventClass) {
fun onEvent(handler: (E) -> Unit) {
this@MiraiEventHookKt.handler = Consumer(handler)
fun onEvent(handler: suspend (E) -> Unit) {
this@MiraiEventHookKt.handler = Consumer {
runBlocking {
handler(it)
}
}
}
fun validChecker(predicate: (E) -> Boolean) {
this@MiraiEventHookKt.validChecker = Predicate(predicate)
fun validChecker(predicate: suspend (E) -> Boolean) {//todo 把 mirai event 变为 suspend, 而不是在这里 run blocking
this@MiraiEventHookKt.validChecker = Predicate {
runBlocking {
predicate(it)
}
}
}
}

View File

@ -2,6 +2,7 @@
package net.mamoe.mirai.event
import kotlinx.coroutines.runBlocking
import kotlin.reflect.KClass
/**
@ -18,21 +19,29 @@ object EventManager : MiraiEventManager()
/**
* 每次事件触发时都会调用 hook
*/
fun <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this, hook))
fun <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: suspend (E) -> Unit) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this) {
runBlocking {
hook(it)
}
})
}
/**
* 当下一次事件触发时调用 hook
*/
fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this, hook))
fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: suspend (E) -> Unit) {
MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this) {
runBlocking {
hook(it)
}
})
}
/**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/
fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: suspend (E) -> Boolean) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple(this, hook))
}
@ -40,28 +49,30 @@ fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
/**
* 每次事件触发时都会调用 hook
*/
fun <C : KClass<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) {
fun <C : KClass<E>, E : MiraiEvent> C.hookAlways(hook: suspend (E) -> Unit) {
this.java.hookAlways(hook)
}
/**
* 当下一次事件触发时调用 hook
*/
fun <C : KClass<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) {
fun <C : KClass<E>, E : MiraiEvent> C.hookOnce(hook: suspend (E) -> Unit) {
this.java.hookOnce(hook)
}
/**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook
*/
fun <C : KClass<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
fun <C : KClass<E>, E : MiraiEvent> C.hookWhile(hook: suspend (E) -> Boolean) {
this.java.hookWhile(hook)
}
private class MiraiEventHookSimple<E : MiraiEvent>(clazz: Class<E>, val hook: (E) -> Boolean) : MiraiEventHook<E>(clazz) {
private class MiraiEventHookSimple<E : MiraiEvent>(clazz: Class<E>, val hook: suspend (E) -> Boolean) : MiraiEventHook<E>(clazz) {
override fun accept(event: MiraiEvent?): Boolean {
@Suppress("UNCHECKED_CAST")
return !hook.invoke(event as E)
return runBlocking {
return@runBlocking !hook.invoke(event as E)
}
}
}

View File

@ -26,7 +26,7 @@ class UnsolvedImage(filename: String, val image: BufferedImage) : Image(getImage
constructor(imageFile: File) : this(imageFile.name, ImageIO.read(imageFile))
constructor(url: URL) : this(File(url.file))
suspend fun upload(session: LoginSession, contact: Contact): CompletableFuture<Unit> {//todo be suspend
fun upload(session: LoginSession, contact: Contact): CompletableFuture<Unit> {
return session.expectPacket<ServerTryGetImageIDResponsePacket> {
toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, contact.number, image) }

View File

@ -117,8 +117,10 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
if (!packet.javaClass.name.endsWith("Encrypted") && !packet.javaClass.name.endsWith("Raw")) {
bot.notice("Packet received: $packet")
}
}
if (packet is ServerEventPacket) {
if (packet is ServerEventPacket) {
NetworkScope.launch {
sendPacket(ClientEventResponsePacket(bot.account.qqNumber, packet.packetId, sessionKey, packet.eventIdentity))
}
}
@ -127,10 +129,18 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
return
}
login.onPacketReceived(packet)
packetHandlers.forEach {
it.instance.onPacketReceived(packet)
}
withContext(NetworkScope.coroutineContext) {
launch {
login.onPacketReceived(packet)
}
packetHandlers.forEach {
launch {
it.instance.onPacketReceived(packet)
}
}
}//awaits all coroutines launched in this block
}
private var socket: DatagramSocket? = null

View File

@ -1,21 +1,6 @@
package net.mamoe.mirai.network
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.asCoroutineDispatcher
import java.util.concurrent.SynchronousQueue
import java.util.concurrent.ThreadPoolExecutor
import java.util.concurrent.TimeUnit
import kotlin.coroutines.CoroutineContext
import kotlinx.coroutines.Dispatchers
object NetworkScope : CoroutineScope {
override val coroutineContext: CoroutineContext
get() = lazy {
ThreadPoolExecutor(
1,
4,
8000, TimeUnit.MILLISECONDS,
SynchronousQueue()
).asCoroutineDispatcher()
}.value//todo improve
}
object NetworkScope : CoroutineScope by CoroutineScope(Dispatchers.Default)