[Review] Move Listener.ConcurrencyKind and Listener.EventPriority to top-level

This commit is contained in:
Him188 2021-01-08 12:41:42 +08:00
parent 4e2108d841
commit 619dafa1ae
15 changed files with 134 additions and 135 deletions

View File

@ -53,9 +53,9 @@ public interface Event {
* *
* 当事件被 [拦截][Event.intercept] , 优先级较低 (靠右) 的监听器将不会被调用. * 当事件被 [拦截][Event.intercept] , 优先级较低 (靠右) 的监听器将不会被调用.
* *
* 优先级为 [Listener.EventPriority.MONITOR] 的监听器不应该调用这个函数. * 优先级为 [EventPriority.MONITOR] 的监听器不应该调用这个函数.
* *
* @see Listener.EventPriority 查看优先级相关信息 * @see EventPriority 查看优先级相关信息
*/ */
public fun intercept() public fun intercept()
} }

View File

@ -19,8 +19,8 @@ import kotlinx.coroutines.*
import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.Channel
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.event.Listener.ConcurrencyKind.CONCURRENT import net.mamoe.mirai.event.ConcurrencyKind.CONCURRENT
import net.mamoe.mirai.event.Listener.ConcurrencyKind.LOCKED import net.mamoe.mirai.event.ConcurrencyKind.LOCKED
import net.mamoe.mirai.event.events.BotEvent import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.internal.event.GlobalEventListeners import net.mamoe.mirai.internal.event.GlobalEventListeners
import net.mamoe.mirai.internal.event.Handler import net.mamoe.mirai.internal.event.Handler
@ -80,7 +80,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
public fun asChannel( public fun asChannel(
capacity: Int = Channel.RENDEZVOUS, capacity: Int = Channel.RENDEZVOUS,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = CONCURRENT, concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
): Channel<out BaseEvent> { ): Channel<out BaseEvent> {
val channel = Channel<BaseEvent>(capacity) val channel = Channel<BaseEvent>(capacity)
@ -120,7 +120,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
* [filter] 允许挂起协程. **过滤器的挂起将被认为是事件监听器的挂起**. * [filter] 允许挂起协程. **过滤器的挂起将被认为是事件监听器的挂起**.
* *
* 过滤器挂起是否会影响事件处理, * 过滤器挂起是否会影响事件处理,
* 取决于 [subscribe] 时的 [Listener.ConcurrencyKind] [Listener.EventPriority]. * 取决于 [subscribe] 时的 [ConcurrencyKind] [EventPriority].
* *
* ## 过滤器异常处理 * ## 过滤器异常处理
* [filter] 抛出异常, 将被包装为 [ExceptionInEventChannelFilterException] 并重新抛出. * [filter] 抛出异常, 将被包装为 [ExceptionInEventChannelFilterException] 并重新抛出.
@ -305,11 +305,11 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
* ## 并发安全性 * ## 并发安全性
* 基于 [concurrency] 参数, 事件监听器可以被允许并行执行. * 基于 [concurrency] 参数, 事件监听器可以被允许并行执行.
* *
* - [concurrency] [Listener.ConcurrencyKind.CONCURRENT], [handler] 可能被并行调用, 需要保证并发安全. * - [concurrency] [ConcurrencyKind.CONCURRENT], [handler] 可能被并行调用, 需要保证并发安全.
* - [concurrency] [Listener.ConcurrencyKind.LOCKED], [handler] 会被 [Mutex] 限制. * - [concurrency] [ConcurrencyKind.LOCKED], [handler] 会被 [Mutex] 限制.
* *
* @param coroutineContext [defaultCoroutineContext] 的基础上, 给事件监听协程的额外的 [CoroutineContext]. * @param coroutineContext [defaultCoroutineContext] 的基础上, 给事件监听协程的额外的 [CoroutineContext].
* @param concurrency 并发类型. 查看 [Listener.ConcurrencyKind] * @param concurrency 并发类型. 查看 [ConcurrencyKind]
* @param priority 监听优先级优先级越高越先执行 * @param priority 监听优先级优先级越高越先执行
* @param handler 事件处理器. 在接收到事件时会调用这个处理器. 其返回值意义参考 [ListeningStatus]. 其异常处理参考上文 * @param handler 事件处理器. 在接收到事件时会调用这个处理器. 其返回值意义参考 [ListeningStatus]. 其异常处理参考上文
* *
@ -331,7 +331,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
@JvmSynthetic @JvmSynthetic
public inline fun <reified E : Event> subscribe( public inline fun <reified E : Event> subscribe(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = LOCKED, concurrency: ConcurrencyKind = LOCKED,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
noinline handler: suspend E.(E) -> ListeningStatus noinline handler: suspend E.(E) -> ListeningStatus
): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority, handler) ): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority, handler)
@ -346,7 +346,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
public fun <E : Event> subscribe( public fun <E : Event> subscribe(
eventClass: KClass<out E>, eventClass: KClass<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = LOCKED, concurrency: ConcurrencyKind = LOCKED,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
handler: suspend E.(E) -> ListeningStatus handler: suspend E.(E) -> ListeningStatus
): Listener<E> = subscribeInternal( ): Listener<E> = subscribeInternal(
@ -372,7 +372,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
@JvmSynthetic @JvmSynthetic
public inline fun <reified E : Event> subscribeAlways( public inline fun <reified E : Event> subscribeAlways(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = CONCURRENT, concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
noinline handler: suspend E.(E) -> Unit noinline handler: suspend E.(E) -> Unit
): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority, handler) ): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority, handler)
@ -386,7 +386,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
public fun <E : Event> subscribeAlways( public fun <E : Event> subscribeAlways(
eventClass: KClass<out E>, eventClass: KClass<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = CONCURRENT, concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
handler: suspend E.(E) -> Unit handler: suspend E.(E) -> Unit
): Listener<E> = subscribeInternal( ): Listener<E> = subscribeInternal(
@ -465,7 +465,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
public fun <E : Event> subscribeAlways( public fun <E : Event> subscribeAlways(
eventClass: Class<out E>, eventClass: Class<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = CONCURRENT, concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
handler: Consumer<E> handler: Consumer<E>
): Listener<E> = subscribeInternal( ): Listener<E> = subscribeInternal(
@ -495,7 +495,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
public fun <E : Event> subscribe( public fun <E : Event> subscribe(
eventClass: Class<out E>, eventClass: Class<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = CONCURRENT, concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
handler: java.util.function.Function<E, ListeningStatus> handler: java.util.function.Function<E, ListeningStatus>
): Listener<E> = subscribeInternal( ): Listener<E> = subscribeInternal(
@ -523,7 +523,7 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
public fun <E : Event> subscribeOnce( public fun <E : Event> subscribeOnce(
eventClass: Class<out E>, eventClass: Class<out E>,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrency: Listener.ConcurrencyKind = CONCURRENT, concurrency: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
handler: Consumer<E> handler: Consumer<E>
): Listener<E> = subscribeInternal( ): Listener<E> = subscribeInternal(
@ -565,8 +565,8 @@ public open class EventChannel<out BaseEvent : Event> @JvmOverloads internal con
@Suppress("FunctionName") @Suppress("FunctionName")
private fun <E : Event> createListener( private fun <E : Event> createListener(
coroutineContext: CoroutineContext, coroutineContext: CoroutineContext,
concurrencyKind: Listener.ConcurrencyKind, concurrencyKind: ConcurrencyKind,
priority: Listener.EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
handler: suspend (E) -> ListeningStatus handler: suspend (E) -> ListeningStatus
): Listener<E> { ): Listener<E> {
val context = this.defaultCoroutineContext + coroutineContext val context = this.defaultCoroutineContext + coroutineContext

View File

@ -34,7 +34,7 @@ import kotlin.internal.LowPriorityInOverloadResolution
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe(
crossinline handler: suspend E.(E) -> ListeningStatus, crossinline handler: suspend E.(E) -> ListeningStatus,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) }
@ -56,7 +56,7 @@ public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe(
crossinline handler: suspend (E) -> ListeningStatus, crossinline handler: suspend (E) -> ListeningStatus,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) }
@ -77,7 +77,7 @@ public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe(
crossinline handler: E.(E) -> ListeningStatus, crossinline handler: E.(E) -> ListeningStatus,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) }
@ -98,7 +98,7 @@ public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribe(
crossinline handler: (E) -> ListeningStatus, crossinline handler: (E) -> ListeningStatus,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribe(E::class, coroutineContext, concurrency, priority) { handler(this) }
@ -118,7 +118,7 @@ public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways(
crossinline handler: suspend (E) -> Unit, crossinline handler: suspend (E) -> Unit,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) }
@ -138,7 +138,7 @@ public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways(
crossinline handler: suspend E.(E) -> Unit, crossinline handler: suspend E.(E) -> Unit,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) }
@ -157,7 +157,7 @@ public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways(
crossinline handler: E.(E) -> Unit, crossinline handler: E.(E) -> Unit,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) }
@ -176,6 +176,6 @@ public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>
public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways( public inline fun <BaseEvent : Event, reified E : Event> EventChannel<BaseEvent>.subscribeAlways(
crossinline handler: (E) -> Unit, crossinline handler: (E) -> Unit,
priority: EventPriority = EventPriority.NORMAL, priority: EventPriority = EventPriority.NORMAL,
concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT, concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT,
coroutineContext: CoroutineContext = EmptyCoroutineContext coroutineContext: CoroutineContext = EmptyCoroutineContext
): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) } ): Listener<E> = subscribeAlways(E::class, coroutineContext, concurrency, priority) { handler(this) }

View File

@ -147,10 +147,10 @@ import kotlin.coroutines.EmptyCoroutineContext
public annotation class EventHandler( public annotation class EventHandler(
/** /**
* 监听器优先级 * 监听器优先级
* @see Listener.EventPriority 查看优先级相关信息 * @see EventPriority 查看优先级相关信息
* @see Event.intercept 拦截事件 * @see Event.intercept 拦截事件
*/ */
public val priority: Listener.EventPriority = EventPriority.NORMAL, public val priority: EventPriority = EventPriority.NORMAL,
/** /**
* 是否自动忽略被 [取消][CancellableEvent.isCancelled] * 是否自动忽略被 [取消][CancellableEvent.isCancelled]
* @see CancellableEvent * @see CancellableEvent
@ -158,9 +158,9 @@ public annotation class EventHandler(
public val ignoreCancelled: Boolean = true, public val ignoreCancelled: Boolean = true,
/** /**
* 并发类型 * 并发类型
* @see Listener.ConcurrencyKind * @see ConcurrencyKind
*/ */
public val concurrency: Listener.ConcurrencyKind = Listener.ConcurrencyKind.CONCURRENT public val concurrency: ConcurrencyKind = ConcurrencyKind.CONCURRENT
) )
/** /**

View File

@ -15,7 +15,7 @@ package net.mamoe.mirai.event
import kotlinx.coroutines.CompletableJob import kotlinx.coroutines.CompletableJob
import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.Mutex
import net.mamoe.mirai.event.Listener.EventPriority.* import net.mamoe.mirai.event.EventPriority.*
/** /**
* 订阅者的状态 * 订阅者的状态
@ -29,9 +29,9 @@ public enum class ListeningStatus {
/** /**
* 表示已停止. * 表示已停止.
* *
* - 若监听器使用 [Listener.ConcurrencyKind.LOCKED], * - 若监听器使用 [ConcurrencyKind.LOCKED],
* 在这之后监听器将会被从监听器列表中删除, 因此不再能接收到事件. * 在这之后监听器将会被从监听器列表中删除, 因此不再能接收到事件.
* - 若使用 [Listener.ConcurrencyKind.CONCURRENT], * - 若使用 [ConcurrencyKind.CONCURRENT],
* 在这之后无法保证立即停止监听. * 在这之后无法保证立即停止监听.
*/ */
STOPPED STOPPED
@ -45,9 +45,29 @@ public enum class ListeningStatus {
*/ */
public interface Listener<in E : Event> : CompletableJob { public interface Listener<in E : Event> : CompletableJob {
/**
* 并发类型
*/
public val concurrencyKind: ConcurrencyKind
/**
* 事件优先级
* @see [EventPriority]
*/
public val priority: EventPriority get() = NORMAL
/**
* 这个方法将会调用 [EventChannel.subscribe] 时提供的参数 `noinline handler: suspend E.(E) -> ListeningStatus`.
*
* 这个函数不会抛出任何异常, 详见 [EventChannel.subscribe]
*/
public suspend fun onEvent(event: E): ListeningStatus
}
public enum class ConcurrencyKind { public enum class ConcurrencyKind {
/** /**
* 并发地同时处理多个事件, 但无法保证 [onEvent] 返回 [ListeningStatus.STOPPED] 后立即停止事件监听. * 并发地同时处理多个事件, 但无法保证 [Listener.onEvent] 返回 [ListeningStatus.STOPPED] 后立即停止事件监听.
*/ */
CONCURRENT, CONCURRENT,
@ -57,16 +77,12 @@ public interface Listener<in E : Event> : CompletableJob {
LOCKED LOCKED
} }
/**
* 并发类型
*/
public val concurrencyKind: ConcurrencyKind
/** /**
* 事件优先级. * 事件优先级.
* *
* 在广播时, 事件监听器的调用顺序为 (从左到右): * 在广播时, 事件监听器的调用顺序为 (从左到右):
* `[HIGHEST]` -> `[HIGH]` -> `[NORMAL]` -> `[LOW]` -> `[LOWEST]` -> `[MONITOR]` * [HIGHEST] -> [HIGH] -> [NORMAL] -> [LOW] -> [LOWEST] -> [MONITOR]
* *
* - 使用 [MONITOR] 优先级的监听器将会被**并行**调用. * - 使用 [MONITOR] 优先级的监听器将会被**并行**调用.
* - 使用其他优先级的监听器都将会**按顺序**调用. * - 使用其他优先级的监听器都将会**按顺序**调用.
@ -93,19 +109,3 @@ public interface Listener<in E : Event> : CompletableJob {
} }
} }
} }
/**
* 事件优先级
* @see [EventPriority]
*/
public val priority: EventPriority get() = NORMAL
/**
* 这个方法将会调用 [EventChannel.subscribe] 时提供的参数 `noinline handler: suspend E.(E) -> ListeningStatus`.
*
* 这个函数不会抛出任何异常, 详见 [EventChannel.subscribe]
*/
public suspend fun onEvent(event: E): ListeningStatus
}
public typealias EventPriority = Listener.EventPriority

View File

@ -32,7 +32,7 @@ import kotlin.reflect.KClass
@JvmSynthetic @JvmSynthetic
public suspend inline fun <reified E : Event> nextEvent( public suspend inline fun <reified E : Event> nextEvent(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
crossinline filter: (E) -> Boolean = { true } crossinline filter: (E) -> Boolean = { true }
): E { ): E {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" } require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
@ -56,7 +56,7 @@ public suspend inline fun <reified E : Event> nextEvent(
@JvmSynthetic @JvmSynthetic
public suspend inline fun <reified E : Event> nextEventOrNull( public suspend inline fun <reified E : Event> nextEventOrNull(
timeoutMillis: Long, timeoutMillis: Long,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
crossinline filter: (E) -> Boolean = { true } crossinline filter: (E) -> Boolean = { true }
): E? { ): E? {
return withTimeoutOrNull(timeoutMillis) { return withTimeoutOrNull(timeoutMillis) {
@ -70,7 +70,7 @@ public suspend inline fun <reified E : Event> nextEventOrNull(
internal suspend inline fun <E : Event> nextEventImpl( internal suspend inline fun <E : Event> nextEventImpl(
eventClass: KClass<E>, eventClass: KClass<E>,
coroutineScope: CoroutineScope, coroutineScope: CoroutineScope,
priority: Listener.EventPriority, priority: EventPriority,
crossinline filter: (E) -> Boolean crossinline filter: (E) -> Boolean
): E = suspendCancellableCoroutine { cont -> ): E = suspendCancellableCoroutine { cont ->
coroutineScope.globalEventChannel().subscribe(eventClass, priority = priority) { coroutineScope.globalEventChannel().subscribe(eventClass, priority = priority) {
@ -90,7 +90,7 @@ internal suspend inline fun <E : BotEvent> nextBotEventImpl(
bot: Bot, bot: Bot,
eventClass: KClass<E>, eventClass: KClass<E>,
coroutineScope: CoroutineScope, coroutineScope: CoroutineScope,
priority: Listener.EventPriority priority: EventPriority
): E = suspendCancellableCoroutine { cont -> ): E = suspendCancellableCoroutine { cont ->
coroutineScope.globalEventChannel().subscribe(eventClass, priority = priority) { coroutineScope.globalEventChannel().subscribe(eventClass, priority = priority) {
try { try {

View File

@ -61,7 +61,7 @@ import net.mamoe.mirai.utils.MiraiExperimentalApi
public suspend inline fun <reified T : MessageEvent> T.whileSelectMessages( public suspend inline fun <reified T : MessageEvent> T.whileSelectMessages(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
filterContext: Boolean = true, filterContext: Boolean = true,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
@BuilderInference crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit @BuilderInference crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
): Unit = whileSelectMessagesImpl(timeoutMillis, filterContext, priority, selectBuilder) ): Unit = whileSelectMessagesImpl(timeoutMillis, filterContext, priority, selectBuilder)
@ -74,7 +74,7 @@ public suspend inline fun <reified T : MessageEvent> T.whileSelectMessages(
public suspend inline fun <reified T : MessageEvent> T.selectMessagesUnit( public suspend inline fun <reified T : MessageEvent> T.selectMessagesUnit(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
filterContext: Boolean = true, filterContext: Boolean = true,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
@BuilderInference crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, Unit>.() -> Unit @BuilderInference crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, Unit>.() -> Unit
): Unit = selectMessagesImpl(timeoutMillis, true, filterContext, priority, selectBuilder) ): Unit = selectMessagesImpl(timeoutMillis, true, filterContext, priority, selectBuilder)
@ -104,7 +104,7 @@ public suspend inline fun <reified T : MessageEvent> T.selectMessagesUnit(
public suspend inline fun <reified T : MessageEvent, R> T.selectMessages( public suspend inline fun <reified T : MessageEvent, R> T.selectMessages(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
filterContext: Boolean = true, filterContext: Boolean = true,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
@BuilderInference @BuilderInference
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, R>.() -> Unit crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, R>.() -> Unit
): R = ): R =
@ -436,7 +436,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
isUnit: Boolean, isUnit: Boolean,
filterContext: Boolean = true, filterContext: Boolean = true,
priority: Listener.EventPriority, priority: EventPriority,
@BuilderInference @BuilderInference
crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, R>.() -> Unit crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, R>.() -> Unit
): R = withSilentTimeoutOrCoroutineScope(timeoutMillis) { ): R = withSilentTimeoutOrCoroutineScope(timeoutMillis) {
@ -486,7 +486,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
// we don't have any way to reduce duplication yet, // we don't have any way to reduce duplication yet,
// until local functions are supported in inline functions // until local functions are supported in inline functions
@Suppress("DuplicatedCode") val subscribeAlways = globalEventChannel().subscribeAlways<T>( @Suppress("DuplicatedCode") val subscribeAlways = globalEventChannel().subscribeAlways<T>(
concurrency = Listener.ConcurrencyKind.LOCKED, concurrency = ConcurrencyKind.LOCKED,
priority = priority priority = priority
) { event -> ) { event ->
if (filterContext && !this.isContextIdenticalWith(this@selectMessagesImpl)) if (filterContext && !this.isContextIdenticalWith(this@selectMessagesImpl))
@ -538,7 +538,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl( internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl(
timeoutMillis: Long, timeoutMillis: Long,
filterContext: Boolean, filterContext: Boolean,
priority: Listener.EventPriority, priority: EventPriority,
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
): Unit = withSilentTimeoutOrCoroutineScope(timeoutMillis) { ): Unit = withSilentTimeoutOrCoroutineScope(timeoutMillis) {
var deferred: CompletableDeferred<Boolean>? = CompletableDeferred() var deferred: CompletableDeferred<Boolean>? = CompletableDeferred()
@ -568,7 +568,7 @@ internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl
// ensure atomic completing // ensure atomic completing
val subscribeAlways = globalEventChannel().subscribeAlways<T>( val subscribeAlways = globalEventChannel().subscribeAlways<T>(
concurrency = Listener.ConcurrencyKind.LOCKED, concurrency = ConcurrencyKind.LOCKED,
priority = priority priority = priority
) { event -> ) { event ->
if (filterContext && !this.isContextIdenticalWith(this@whileSelectMessagesImpl)) if (filterContext && !this.isContextIdenticalWith(this@whileSelectMessagesImpl))

View File

@ -16,7 +16,7 @@ package net.mamoe.mirai.event
import net.mamoe.mirai.Bot import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.OtherClient import net.mamoe.mirai.contact.OtherClient
import net.mamoe.mirai.contact.Stranger import net.mamoe.mirai.contact.Stranger
import net.mamoe.mirai.event.Listener.ConcurrencyKind.CONCURRENT import net.mamoe.mirai.event.ConcurrencyKind.CONCURRENT
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.message.data.content import net.mamoe.mirai.message.data.content
import kotlin.contracts.InvocationKind import kotlin.contracts.InvocationKind
@ -75,8 +75,8 @@ public typealias MessageEventSubscribersBuilder = MessageSubscribersBuilder<Mess
*/ */
public fun <R> EventChannel<*>.subscribeMessages( public fun <R> EventChannel<*>.subscribeMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
listeners: MessageEventSubscribersBuilder.() -> R listeners: MessageEventSubscribersBuilder.() -> R
): R { ): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -93,8 +93,8 @@ public typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<Grou
*/ */
public fun <R> EventChannel<*>.subscribeGroupMessages( public fun <R> EventChannel<*>.subscribeGroupMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
listeners: GroupMessageSubscribersBuilder.() -> R listeners: GroupMessageSubscribersBuilder.() -> R
): R { ): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -111,8 +111,8 @@ public typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<Fri
*/ */
public fun <R> EventChannel<*>.subscribeFriendMessages( public fun <R> EventChannel<*>.subscribeFriendMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
listeners: FriendMessageSubscribersBuilder.() -> R listeners: FriendMessageSubscribersBuilder.() -> R
): R { ): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -129,8 +129,8 @@ public typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder<TempM
*/ */
public fun <R> EventChannel<*>.subscribeTempMessages( public fun <R> EventChannel<*>.subscribeTempMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
listeners: TempMessageSubscribersBuilder.() -> R listeners: TempMessageSubscribersBuilder.() -> R
): R { ): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -148,8 +148,8 @@ public typealias StrangerMessageSubscribersBuilder = MessageSubscribersBuilder<S
*/ */
public fun <R> EventChannel<*>.subscribeStrangerMessages( public fun <R> EventChannel<*>.subscribeStrangerMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
listeners: StrangerMessageSubscribersBuilder.() -> R listeners: StrangerMessageSubscribersBuilder.() -> R
): R { ): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -168,8 +168,8 @@ public typealias OtherClientMessageSubscribersBuilder = MessageSubscribersBuilde
*/ */
public fun <R> EventChannel<*>.subscribeOtherClientMessages( public fun <R> EventChannel<*>.subscribeOtherClientMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT, concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
listeners: OtherClientMessageSubscribersBuilder.() -> R listeners: OtherClientMessageSubscribersBuilder.() -> R
): R { ): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) } contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -185,8 +185,8 @@ private typealias MessageSubscriberBuilderConstructor<E> = (
private inline fun <reified E : MessageEvent> EventChannel<*>.createBuilder( private inline fun <reified E : MessageEvent> EventChannel<*>.createBuilder(
constructor: MessageSubscriberBuilderConstructor<E>, constructor: MessageSubscriberBuilderConstructor<E>,
coroutineContext: CoroutineContext, coroutineContext: CoroutineContext,
concurrencyKind: Listener.ConcurrencyKind, concurrencyKind: ConcurrencyKind,
priority: Listener.EventPriority priority: EventPriority
): MessageSubscribersBuilder<E, Listener<E>, Unit, Unit> = constructor(Unit) { filter, listener -> ): MessageSubscribersBuilder<E, Listener<E>, Unit, Unit> = constructor(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) { subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.content val toString = this.message.content

View File

@ -34,7 +34,7 @@ import kotlin.reflect.KClass
@JvmSynthetic @JvmSynthetic
public suspend inline fun <reified E : Event, R : Any> syncFromEvent( public suspend inline fun <reified E : Event, R : Any> syncFromEvent(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R? crossinline mapper: suspend E.(E) -> R?
): R { ): R {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" } require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
@ -67,7 +67,7 @@ public suspend inline fun <reified E : Event, R : Any> syncFromEvent(
@JvmSynthetic @JvmSynthetic
public suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull( public suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
timeoutMillis: Long, timeoutMillis: Long,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R? crossinline mapper: suspend E.(E) -> R?
): R? { ): R? {
require(timeoutMillis > 0) { "timeoutMillis must be > 0" } require(timeoutMillis > 0) { "timeoutMillis must be > 0" }
@ -96,7 +96,7 @@ public suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
public inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNull( public inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNull(
timeoutMillis: Long, timeoutMillis: Long,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R? crossinline mapper: suspend E.(E) -> R?
): Deferred<R?> { ): Deferred<R?> {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" } require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
@ -125,7 +125,7 @@ public inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEventOrNu
public inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEvent( public inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEvent(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R? crossinline mapper: suspend E.(E) -> R?
): Deferred<R> { ): Deferred<R> {
require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" } require(timeoutMillis == -1L || timeoutMillis > 0) { "timeoutMillis must be -1 or > 0" }
@ -144,7 +144,7 @@ public inline fun <reified E : Event, R : Any> CoroutineScope.asyncFromEvent(
internal suspend inline fun <E : Event, R> syncFromEventImpl( internal suspend inline fun <E : Event, R> syncFromEventImpl(
eventClass: KClass<E>, eventClass: KClass<E>,
coroutineScope: CoroutineScope, coroutineScope: CoroutineScope,
priority: Listener.EventPriority, priority: EventPriority,
crossinline mapper: suspend E.(E) -> R? crossinline mapper: suspend E.(E) -> R?
): R = suspendCancellableCoroutine { cont -> ): R = suspendCancellableCoroutine { cont ->
coroutineScope.globalEventChannel().subscribe(eventClass, priority = priority) { coroutineScope.globalEventChannel().subscribe(eventClass, priority = priority) {

View File

@ -29,14 +29,14 @@ internal class Handler<in E : Event> internal constructor(
parentJob: Job?, parentJob: Job?,
subscriberContext: CoroutineContext, subscriberContext: CoroutineContext,
@JvmField val handler: suspend (E) -> ListeningStatus, @JvmField val handler: suspend (E) -> ListeningStatus,
override val concurrencyKind: Listener.ConcurrencyKind, override val concurrencyKind: ConcurrencyKind,
override val priority: Listener.EventPriority override val priority: EventPriority
) : Listener<E>, CompletableJob by SupervisorJob(parentJob) { // avoid being cancelled on handling event ) : Listener<E>, CompletableJob by SupervisorJob(parentJob) { // avoid being cancelled on handling event
private val subscriberContext: CoroutineContext = subscriberContext + this // override Job. private val subscriberContext: CoroutineContext = subscriberContext + this // override Job.
val lock: Mutex? = when (concurrencyKind) { val lock: Mutex? = when (concurrencyKind) {
Listener.ConcurrencyKind.LOCKED -> Mutex() ConcurrencyKind.LOCKED -> Mutex()
else -> null else -> null
} }
@ -78,14 +78,14 @@ internal object GlobalEventListeners {
init { init {
val map = val map =
EnumMap<Listener.EventPriority, ConcurrentLinkedQueue<ListenerRegistry>>(Listener.EventPriority::class.java) EnumMap<EventPriority, ConcurrentLinkedQueue<ListenerRegistry>>(EventPriority::class.java)
EventPriority.values().forEach { EventPriority.values().forEach {
map[it] = ConcurrentLinkedQueue() map[it] = ConcurrentLinkedQueue()
} }
ALL_LEVEL_REGISTRIES = map ALL_LEVEL_REGISTRIES = map
} }
operator fun get(priority: Listener.EventPriority): ConcurrentLinkedQueue<ListenerRegistry> = operator fun get(priority: EventPriority): ConcurrentLinkedQueue<ListenerRegistry> =
ALL_LEVEL_REGISTRIES[priority]!! ALL_LEVEL_REGISTRIES[priority]!!
} }
@ -105,7 +105,7 @@ internal inline fun <E, T : Iterable<E>> T.forEach0(block: T.(E) -> Unit) {
internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired( internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired(
event: E event: E
) { ) {
for (p in Listener.EventPriority.prioritiesExcludedMonitor) { for (p in EventPriority.prioritiesExcludedMonitor) {
GlobalEventListeners[p].forEach0 { registeredRegistry -> GlobalEventListeners[p].forEach0 { registeredRegistry ->
if (event.isIntercepted) { if (event.isIntercepted) {
return return
@ -113,14 +113,14 @@ internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired(
if (!registeredRegistry.type.isInstance(event)) return@forEach0 if (!registeredRegistry.type.isInstance(event)) return@forEach0
val listener = registeredRegistry.listener val listener = registeredRegistry.listener
when (listener.concurrencyKind) { when (listener.concurrencyKind) {
Listener.ConcurrencyKind.LOCKED -> { ConcurrencyKind.LOCKED -> {
(listener as Handler).lock!!.withLock { (listener as Handler).lock!!.withLock {
if (listener.onEvent(event) == ListeningStatus.STOPPED) { if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry) remove(registeredRegistry)
} }
} }
} }
Listener.ConcurrencyKind.CONCURRENT -> { ConcurrencyKind.CONCURRENT -> {
if (listener.onEvent(event) == ListeningStatus.STOPPED) { if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry) remove(registeredRegistry)
} }
@ -137,14 +137,14 @@ internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired(
val listener = registeredRegistry.listener val listener = registeredRegistry.listener
launch { launch {
when (listener.concurrencyKind) { when (listener.concurrencyKind) {
Listener.ConcurrencyKind.LOCKED -> { ConcurrencyKind.LOCKED -> {
(listener as Handler).lock!!.withLock { (listener as Handler).lock!!.withLock {
if (listener.onEvent(event) == ListeningStatus.STOPPED) { if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry) remove(registeredRegistry)
} }
} }
} }
Listener.ConcurrencyKind.CONCURRENT -> { ConcurrencyKind.CONCURRENT -> {
if (listener.onEvent(event) == ListeningStatus.STOPPED) { if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry) remove(registeredRegistry)
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2020 Mamoe Technologies and contributors. * Copyright 2019-2021 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -16,7 +16,6 @@ package net.mamoe.mirai.message
import kotlinx.coroutines.Deferred import kotlinx.coroutines.Deferred
import kotlinx.coroutines.async import kotlinx.coroutines.async
import net.mamoe.mirai.event.EventPriority import net.mamoe.mirai.event.EventPriority
import net.mamoe.mirai.event.Listener
import net.mamoe.mirai.event.events.* import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.syncFromEvent import net.mamoe.mirai.event.syncFromEvent
import net.mamoe.mirai.event.syncFromEventOrNull import net.mamoe.mirai.event.syncFromEventOrNull
@ -46,7 +45,7 @@ public fun MessageEvent.isContextIdenticalWith(another: MessageEvent): Boolean {
@JvmSynthetic @JvmSynthetic
public suspend inline fun <reified P : MessageEvent> P.nextMessage( public suspend inline fun <reified P : MessageEvent> P.nextMessage(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true } noinline filter: suspend P.(P) -> Boolean = { true }
): MessageChain { ): MessageChain {
return syncFromEvent<P, P>(timeoutMillis, priority) { return syncFromEvent<P, P>(timeoutMillis, priority) {
@ -68,7 +67,7 @@ public suspend inline fun <reified P : MessageEvent> P.nextMessage(
@JvmSynthetic @JvmSynthetic
public suspend inline fun <reified P : MessageEvent> P.nextMessageOrNull( public suspend inline fun <reified P : MessageEvent> P.nextMessageOrNull(
timeoutMillis: Long, timeoutMillis: Long,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true } noinline filter: suspend P.(P) -> Boolean = { true }
): MessageChain? { ): MessageChain? {
require(timeoutMillis > 0) { "timeoutMillis must be > 0" } require(timeoutMillis > 0) { "timeoutMillis must be > 0" }
@ -84,7 +83,7 @@ public suspend inline fun <reified P : MessageEvent> P.nextMessageOrNull(
public inline fun <reified P : MessageEvent> P.nextMessageAsync( public inline fun <reified P : MessageEvent> P.nextMessageAsync(
timeoutMillis: Long = -1, timeoutMillis: Long = -1,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true } noinline filter: suspend P.(P) -> Boolean = { true }
): Deferred<MessageChain> { ): Deferred<MessageChain> {
return this.bot.async(coroutineContext) { return this.bot.async(coroutineContext) {
@ -101,7 +100,7 @@ public inline fun <reified P : MessageEvent> P.nextMessageAsync(
public inline fun <reified P : MessageEvent> P.nextMessageOrNullAsync( public inline fun <reified P : MessageEvent> P.nextMessageOrNullAsync(
timeoutMillis: Long, timeoutMillis: Long,
coroutineContext: CoroutineContext = EmptyCoroutineContext, coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR, priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true } noinline filter: suspend P.(P) -> Boolean = { true }
): Deferred<MessageChain?> { ): Deferred<MessageChain?> {
require(timeoutMillis > 0) { "timeoutMillis must be > 0" } require(timeoutMillis > 0) { "timeoutMillis must be > 0" }

View File

@ -52,7 +52,7 @@ class EventTests {
resetEventListeners() resetEventListeners()
var listeners = 0 var listeners = 0
val counter = AtomicInteger(0) val counter = AtomicInteger(0)
for (p in Listener.EventPriority.values()) { for (p in EventPriority.values()) {
repeat(2333) { repeat(2333) {
listeners++ listeners++
GlobalScope.globalEventChannel().subscribeAlways<ParentEvent> { GlobalScope.globalEventChannel().subscribeAlways<ParentEvent> {
@ -78,7 +78,7 @@ class EventTests {
val registered = AtomicInteger() val registered = AtomicInteger()
coroutineScope { coroutineScope {
println("Step 0") println("Step 0")
for (priority in Listener.EventPriority.values()) { for (priority in EventPriority.values()) {
launch { launch {
repeat(5000) { repeat(5000) {
registered.getAndIncrement() registered.getAndIncrement()
@ -216,7 +216,7 @@ class EventTests {
} }
*/ */
fun resetEventListeners() { fun resetEventListeners() {
for (p in Listener.EventPriority.values()) { for (p in EventPriority.values()) {
GlobalEventListeners[p].clear() GlobalEventListeners[p].clear()
} }
} }
@ -278,11 +278,11 @@ class EventTests {
step.step(1) step.step(1)
ListeningStatus.LISTENING ListeningStatus.LISTENING
} }
subscribe<PriorityTestEvent>(priority = Listener.EventPriority.HIGH) { subscribe<PriorityTestEvent>(priority = EventPriority.HIGH) {
step.step(0) step.step(0)
ListeningStatus.LISTENING ListeningStatus.LISTENING
} }
subscribe<PriorityTestEvent>(priority = Listener.EventPriority.LOW) { subscribe<PriorityTestEvent>(priority = EventPriority.LOW) {
step.step(3) step.step(3)
ListeningStatus.LISTENING ListeningStatus.LISTENING
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2019-2020 Mamoe Technologies and contributors. * Copyright 2019-2021 Mamoe Technologies and contributors.
* *
* 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证. * 此源代码的使用受 GNU AFFERO GENERAL PUBLIC LICENSE version 3 许可证的约束, 可以在以下链接找到该许可证.
* Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link. * Use of this source code is governed by the GNU AGPLv3 license that can be found through the following link.
@ -135,13 +135,13 @@ internal class JvmMethodEventsTest {
fun getCalled() = called.get() fun getCalled() = called.get()
@Suppress("unused") @Suppress("unused")
@EventHandler(Listener.EventPriority.HIGHEST) @EventHandler(EventPriority.HIGHEST)
private suspend fun TestEvent.`suspend receiver param Unit`(event: TestEvent) { private suspend fun TestEvent.`suspend receiver param Unit`(event: TestEvent) {
intercept() intercept()
called.getAndIncrement() called.getAndIncrement()
} }
@EventHandler(Listener.EventPriority.MONITOR) @EventHandler(EventPriority.MONITOR)
@Suppress("unused") @Suppress("unused")
private fun TestEvent.`receiver param LS`(event: TestEvent): ListeningStatus { private fun TestEvent.`receiver param LS`(event: TestEvent): ListeningStatus {
called.getAndIncrement() called.getAndIncrement()

View File

@ -24,7 +24,7 @@ import net.mamoe.mirai.Bot
import net.mamoe.mirai.contact.ContactList import net.mamoe.mirai.contact.ContactList
import net.mamoe.mirai.contact.OtherClient import net.mamoe.mirai.contact.OtherClient
import net.mamoe.mirai.event.* import net.mamoe.mirai.event.*
import net.mamoe.mirai.event.Listener.EventPriority.MONITOR import net.mamoe.mirai.event.EventPriority.MONITOR
import net.mamoe.mirai.event.events.BotEvent import net.mamoe.mirai.event.events.BotEvent
import net.mamoe.mirai.event.events.BotOfflineEvent import net.mamoe.mirai.event.events.BotOfflineEvent
import net.mamoe.mirai.event.events.BotReloginEvent import net.mamoe.mirai.event.events.BotReloginEvent
@ -94,7 +94,7 @@ internal abstract class AbstractBot<N : BotNetworkHandler> constructor(
private val offlineListener: Listener<BotOfflineEvent> = private val offlineListener: Listener<BotOfflineEvent> =
this@AbstractBot.eventChannel.subscribeAlways( this@AbstractBot.eventChannel.subscribeAlways(
priority = MONITOR, priority = MONITOR,
concurrency = Listener.ConcurrencyKind.LOCKED concurrency = ConcurrencyKind.LOCKED
) { event -> ) { event ->
if (!event.bot.isActive) { if (!event.bot.isActive) {
// bot closed // bot closed

View File

@ -479,7 +479,7 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
init { init {
@Suppress("RemoveRedundantQualifierName") @Suppress("RemoveRedundantQualifierName")
val listener = bot.eventChannel.subscribeAlways<BotReloginEvent>(priority = Listener.EventPriority.MONITOR) { val listener = bot.eventChannel.subscribeAlways<BotReloginEvent>(priority = EventPriority.MONITOR) {
this@QQAndroidBotNetworkHandler.launch { syncMessageSvc() } this@QQAndroidBotNetworkHandler.launch { syncMessageSvc() }
} }
supervisor.invokeOnCompletion { listener.cancel() } supervisor.invokeOnCompletion { listener.cancel() }