1
0
mirror of https://github.com/mamoe/mirai.git synced 2025-04-05 07:10:11 +08:00

Support object implementations of Event

This commit is contained in:
Him188 2020-05-16 15:32:09 +08:00
parent 23273718fe
commit e4e526ca80
3 changed files with 36 additions and 12 deletions
mirai-core/src
commonMain/kotlin/net.mamoe.mirai/event
jvmMain/kotlin/net/mamoe/mirai/event

View File

@ -12,11 +12,14 @@
package net.mamoe.mirai.event
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import net.mamoe.mirai.JavaFriendlyAPI
import net.mamoe.mirai.event.internal.broadcastInternal
import net.mamoe.mirai.utils.MiraiExperimentalAPI
import net.mamoe.mirai.utils.SinceMirai
import net.mamoe.mirai.utils.internal.runBlocking
import kotlin.jvm.JvmField
import kotlin.jvm.JvmName
import kotlin.jvm.JvmSynthetic
import kotlin.jvm.Volatile
@ -28,6 +31,9 @@ import kotlin.jvm.Volatile
*
* 所有 [Event] 都应继承 [AbstractEvent] 而不要直接实现 [Event]. 否则将无法广播也无法监听.
*
* ### 广播
* 广播事件的唯一方式为 [broadcast].
*
* @see subscribeAlways
* @see subscribeOnce
*
@ -53,7 +59,9 @@ interface Event {
*
* 当事件被 [拦截][Event.intercept] , 优先级较低 (靠右) 的监听器将不会被调用.
*
* @see [Listener.EventPriority] 查看优先级相关信息
* 优先级为 [Listener.EventPriority.MONITOR] 的监听器不应该调用这个函数.
*
* @see Listener.EventPriority 查看优先级相关信息
*/
@SinceMirai("1.0.0")
fun intercept()
@ -81,8 +89,13 @@ abstract class AbstractEvent : Event {
final override val DoNotImplementThisClassButExtendAbstractEvent: Nothing
get() = throw Error("Shouldn't be reached")
/** 限制一个事件实例不能并行广播. (适用于 object 广播的情况) */
@JvmField
internal val broadCastLock = Mutex()
@JvmField
@Volatile
private var _intercepted = false
internal var _intercepted = false
@Volatile
private var _cancelled = false
@ -142,14 +155,24 @@ interface CancellableEvent : Event {
/**
* 广播一个事件的唯一途径.
* @see __broadcastJava
*
* 当事件被实现为 Kotlin `object` , 同一时刻只能有一个 [广播][broadcast] 存在. 较晚执行的 [广播][broadcast] 将会挂起协程并等待之前的广播任务结束.
*
* @see __broadcastJava Java 使用
*/
@JvmSynthetic
suspend fun <E : Event> E.broadcast(): E = apply {
check(this is AbstractEvent) {
"Events must extend AbstractEvent"
}
if (this is BroadcastControllable && !this.shouldBroadcast) {
return@apply
}
this@broadcast.broadcastInternal() // inline, no extra cost
this.broadCastLock.withLock {
this._intercepted = false
this.broadcastInternal() // inline, no extra cost
}
}
/**
@ -164,7 +187,7 @@ fun <E : Event> E.__broadcastJava(): E = apply {
if (this is BroadcastControllable && !this.shouldBroadcast) {
return@apply
}
runBlocking { this@__broadcastJava.broadcastInternal() }
runBlocking { this@__broadcastJava.broadcast() }
}
/**

View File

@ -126,13 +126,13 @@ internal expect class MiraiAtomicBoolean(initial: Boolean) {
// inline: NO extra Continuation
@Suppress("UNCHECKED_CAST")
internal suspend inline fun Event.broadcastInternal() {
internal suspend inline fun AbstractEvent.broadcastInternal() {
if (EventDisabled) return
callAndRemoveIfRequired(this@broadcastInternal as? AbstractEvent ?: error("Events must extends AbstractEvent"))
callAndRemoveIfRequired(this@broadcastInternal)
}
@Suppress("DuplicatedCode")
internal suspend fun <E : AbstractEvent> callAndRemoveIfRequired(
internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired(
event: E
) {
for (p in Listener.EventPriority.valuesExceptMonitor) {

View File

@ -28,9 +28,10 @@ import kotlin.reflect.jvm.kotlinFunction
*
* ### Kotlin 函数
* Kotlin 函数要求:
* - 接收者和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都)
* - 接收者 ( receiver) 和函数参数: 所标注的 Kotlin 函数必须至少拥有一个接收者或一个函数参数, 或二者都具有. 接收者和函数参数的类型必须相同 (如果二者都存在)
* 接收者或函数参数的类型都必须为 [Event] 或其子类.
* - 返回值: [Unit] 或不指定返回值时将注册为 [CoroutineScope.subscribeAlways], [ListeningStatus] 时将注册为 [CoroutineScope.subscribe]
* - 返回值: [Unit] 或不指定返回值时将注册为 [CoroutineScope.subscribeAlways], [ListeningStatus] 时将注册为 [CoroutineScope.subscribe].
* 任何其他类型的返回值将会在注册时抛出异常.
*
* 所有 Kotlin `suspend` 的函数都将会在 [Dispatchers.IO] 中调用
*
@ -118,8 +119,8 @@ import kotlin.reflect.jvm.kotlinFunction
annotation class EventHandler(
/**
* 监听器优先级
* @see Listener.EventPriority
* @see Event.intercept
* @see Listener.EventPriority 查看优先级相关信息
* @see Event.intercept 拦截事件
*/
val priority: Listener.EventPriority = EventPriority.NORMAL,
/**