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) return image.upload(session, this)
} }

View File

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

View File

@ -2,6 +2,7 @@
package net.mamoe.mirai.event package net.mamoe.mirai.event
import kotlinx.coroutines.runBlocking
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
@ -18,21 +19,29 @@ object EventManager : MiraiEventManager()
/** /**
* 每次事件触发时都会调用 hook * 每次事件触发时都会调用 hook
*/ */
fun <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: (E) -> Unit) { fun <C : Class<E>, E : MiraiEvent> C.hookAlways(hook: suspend (E) -> Unit) {
MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this, hook)) MiraiEventManager.getInstance().hookAlways(MiraiEventHook<E>(this) {
runBlocking {
hook(it)
}
})
} }
/** /**
* 当下一次事件触发时调用 hook * 当下一次事件触发时调用 hook
*/ */
fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: (E) -> Unit) { fun <C : Class<E>, E : MiraiEvent> C.hookOnce(hook: suspend (E) -> Unit) {
MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this, hook)) MiraiEventManager.getInstance().hookOnce(MiraiEventHook<E>(this) {
runBlocking {
hook(it)
}
})
} }
/** /**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 hook * 每次事件触发时都会调用 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)) MiraiEventManager.getInstance().hookAlways(MiraiEventHookSimple(this, hook))
} }
@ -40,28 +49,30 @@ fun <C : Class<E>, E : MiraiEvent> C.hookWhile(hook: (E) -> Boolean) {
/** /**
* 每次事件触发时都会调用 hook * 每次事件触发时都会调用 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) this.java.hookAlways(hook)
} }
/** /**
* 当下一次事件触发时调用 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) this.java.hookOnce(hook)
} }
/** /**
* 每次事件触发时都会调用 hook, 直到 hook 返回 false 时停止 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) 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 { override fun accept(event: MiraiEvent?): Boolean {
@Suppress("UNCHECKED_CAST") @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(imageFile: File) : this(imageFile.name, ImageIO.read(imageFile))
constructor(url: URL) : this(File(url.file)) 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> { return session.expectPacket<ServerTryGetImageIDResponsePacket> {
toSend { ClientTryGetImageIDPacket(session.bot.account.qqNumber, session.sessionKey, contact.number, image) } 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")) { if (!packet.javaClass.name.endsWith("Encrypted") && !packet.javaClass.name.endsWith("Raw")) {
bot.notice("Packet received: $packet") 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)) sendPacket(ClientEventResponsePacket(bot.account.qqNumber, packet.packetId, sessionKey, packet.eventIdentity))
} }
} }
@ -127,10 +129,18 @@ internal class BotNetworkHandlerImpl(private val bot: Bot) : BotNetworkHandler {
return return
} }
login.onPacketReceived(packet) withContext(NetworkScope.coroutineContext) {
packetHandlers.forEach { launch {
it.instance.onPacketReceived(packet) login.onPacketReceived(packet)
} }
packetHandlers.forEach {
launch {
it.instance.onPacketReceived(packet)
}
}
}//awaits all coroutines launched in this block
} }
private var socket: DatagramSocket? = null private var socket: DatagramSocket? = null

View File

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