[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] , 优先级较低 (靠右) 的监听器将不会被调用.
*
* 优先级为 [Listener.EventPriority.MONITOR] 的监听器不应该调用这个函数.
* 优先级为 [EventPriority.MONITOR] 的监听器不应该调用这个函数.
*
* @see Listener.EventPriority 查看优先级相关信息
* @see EventPriority 查看优先级相关信息
*/
public fun intercept()
}

View File

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

View File

@ -147,10 +147,10 @@ import kotlin.coroutines.EmptyCoroutineContext
public annotation class EventHandler(
/**
* 监听器优先级
* @see Listener.EventPriority 查看优先级相关信息
* @see EventPriority 查看优先级相关信息
* @see Event.intercept 拦截事件
*/
public val priority: Listener.EventPriority = EventPriority.NORMAL,
public val priority: EventPriority = EventPriority.NORMAL,
/**
* 是否自动忽略被 [取消][CancellableEvent.isCancelled]
* @see CancellableEvent
@ -158,9 +158,9 @@ public annotation class EventHandler(
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.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
@ -45,54 +45,11 @@ public enum class ListeningStatus {
*/
public interface Listener<in E : Event> : CompletableJob {
public enum class ConcurrencyKind {
/**
* 并发地同时处理多个事件, 但无法保证 [onEvent] 返回 [ListeningStatus.STOPPED] 后立即停止事件监听.
*/
CONCURRENT,
/**
* 使用 [Mutex] 保证同一时刻只处理一个事件.
*/
LOCKED
}
/**
* 并发类型
*/
public val concurrencyKind: ConcurrencyKind
/**
* 事件优先级.
*
* 在广播时, 事件监听器的调用顺序为 (从左到右):
* `[HIGHEST]` -> `[HIGH]` -> `[NORMAL]` -> `[LOW]` -> `[LOWEST]` -> `[MONITOR]`
*
* - 使用 [MONITOR] 优先级的监听器将会被**并行**调用.
* - 使用其他优先级的监听器都将会**按顺序**调用.
* 因此一个监听器的挂起可以阻塞事件处理过程而导致低优先级的监听器较晚处理.
*
* 当事件被 [拦截][Event.intercept] , 优先级较低 (靠右) 的监听器将不会被调用.
*/
public enum class EventPriority {
HIGHEST, HIGH, NORMAL, LOW, LOWEST,
/**
* 最低的优先级.
*
* 使用此优先级的监听器应遵循约束:
* - [拦截事件][Event.intercept]
*/
MONITOR;
internal companion object {
@JvmStatic
internal val prioritiesExcludedMonitor: Array<EventPriority> = run {
values().filter { it != MONITOR }.toTypedArray()
}
}
}
/**
* 事件优先级
@ -108,4 +65,47 @@ public interface Listener<in E : Event> : CompletableJob {
public suspend fun onEvent(event: E): ListeningStatus
}
public typealias EventPriority = Listener.EventPriority
public enum class ConcurrencyKind {
/**
* 并发地同时处理多个事件, 但无法保证 [Listener.onEvent] 返回 [ListeningStatus.STOPPED] 后立即停止事件监听.
*/
CONCURRENT,
/**
* 使用 [Mutex] 保证同一时刻只处理一个事件.
*/
LOCKED
}
/**
* 事件优先级.
*
* 在广播时, 事件监听器的调用顺序为 (从左到右):
* [HIGHEST] -> [HIGH] -> [NORMAL] -> [LOW] -> [LOWEST] -> [MONITOR]
*
* - 使用 [MONITOR] 优先级的监听器将会被**并行**调用.
* - 使用其他优先级的监听器都将会**按顺序**调用.
* 因此一个监听器的挂起可以阻塞事件处理过程而导致低优先级的监听器较晚处理.
*
* 当事件被 [拦截][Event.intercept] , 优先级较低 (靠右) 的监听器将不会被调用.
*/
public enum class EventPriority {
HIGHEST, HIGH, NORMAL, LOW, LOWEST,
/**
* 最低的优先级.
*
* 使用此优先级的监听器应遵循约束:
* - [拦截事件][Event.intercept]
*/
MONITOR;
internal companion object {
@JvmStatic
internal val prioritiesExcludedMonitor: Array<EventPriority> = run {
values().filter { it != MONITOR }.toTypedArray()
}
}
}

View File

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

View File

@ -61,7 +61,7 @@ import net.mamoe.mirai.utils.MiraiExperimentalApi
public suspend inline fun <reified T : MessageEvent> T.whileSelectMessages(
timeoutMillis: Long = -1,
filterContext: Boolean = true,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
@BuilderInference crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
): 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(
timeoutMillis: Long = -1,
filterContext: Boolean = true,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
@BuilderInference crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, Unit>.() -> Unit
): 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(
timeoutMillis: Long = -1,
filterContext: Boolean = true,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
@BuilderInference
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, R>.() -> Unit
): R =
@ -436,7 +436,7 @@ internal suspend inline fun <reified T : MessageEvent, R> T.selectMessagesImpl(
timeoutMillis: Long = -1,
isUnit: Boolean,
filterContext: Boolean = true,
priority: Listener.EventPriority,
priority: EventPriority,
@BuilderInference
crossinline selectBuilder: @MessageDsl MessageSelectBuilderUnit<T, R>.() -> Unit
): 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,
// until local functions are supported in inline functions
@Suppress("DuplicatedCode") val subscribeAlways = globalEventChannel().subscribeAlways<T>(
concurrency = Listener.ConcurrencyKind.LOCKED,
concurrency = ConcurrencyKind.LOCKED,
priority = priority
) { event ->
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(
timeoutMillis: Long,
filterContext: Boolean,
priority: Listener.EventPriority,
priority: EventPriority,
crossinline selectBuilder: @MessageDsl MessageSelectBuilder<T, Boolean>.() -> Unit
): Unit = withSilentTimeoutOrCoroutineScope(timeoutMillis) {
var deferred: CompletableDeferred<Boolean>? = CompletableDeferred()
@ -568,7 +568,7 @@ internal suspend inline fun <reified T : MessageEvent> T.whileSelectMessagesImpl
// ensure atomic completing
val subscribeAlways = globalEventChannel().subscribeAlways<T>(
concurrency = Listener.ConcurrencyKind.LOCKED,
concurrency = ConcurrencyKind.LOCKED,
priority = priority
) { event ->
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.contact.OtherClient
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.message.data.content
import kotlin.contracts.InvocationKind
@ -75,8 +75,8 @@ public typealias MessageEventSubscribersBuilder = MessageSubscribersBuilder<Mess
*/
public fun <R> EventChannel<*>.subscribeMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.MONITOR,
listeners: MessageEventSubscribersBuilder.() -> R
): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -93,8 +93,8 @@ public typealias GroupMessageSubscribersBuilder = MessageSubscribersBuilder<Grou
*/
public fun <R> EventChannel<*>.subscribeGroupMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.MONITOR,
listeners: GroupMessageSubscribersBuilder.() -> R
): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -111,8 +111,8 @@ public typealias FriendMessageSubscribersBuilder = MessageSubscribersBuilder<Fri
*/
public fun <R> EventChannel<*>.subscribeFriendMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.MONITOR,
listeners: FriendMessageSubscribersBuilder.() -> R
): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -129,8 +129,8 @@ public typealias TempMessageSubscribersBuilder = MessageSubscribersBuilder<TempM
*/
public fun <R> EventChannel<*>.subscribeTempMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.MONITOR,
listeners: TempMessageSubscribersBuilder.() -> R
): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -148,8 +148,8 @@ public typealias StrangerMessageSubscribersBuilder = MessageSubscribersBuilder<S
*/
public fun <R> EventChannel<*>.subscribeStrangerMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.MONITOR,
listeners: StrangerMessageSubscribersBuilder.() -> R
): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -168,8 +168,8 @@ public typealias OtherClientMessageSubscribersBuilder = MessageSubscribersBuilde
*/
public fun <R> EventChannel<*>.subscribeOtherClientMessages(
coroutineContext: CoroutineContext = EmptyCoroutineContext,
concurrencyKind: Listener.ConcurrencyKind = CONCURRENT,
priority: Listener.EventPriority = EventPriority.MONITOR,
concurrencyKind: ConcurrencyKind = CONCURRENT,
priority: EventPriority = EventPriority.MONITOR,
listeners: OtherClientMessageSubscribersBuilder.() -> R
): R {
contract { callsInPlace(listeners, InvocationKind.EXACTLY_ONCE) }
@ -185,8 +185,8 @@ private typealias MessageSubscriberBuilderConstructor<E> = (
private inline fun <reified E : MessageEvent> EventChannel<*>.createBuilder(
constructor: MessageSubscriberBuilderConstructor<E>,
coroutineContext: CoroutineContext,
concurrencyKind: Listener.ConcurrencyKind,
priority: Listener.EventPriority
concurrencyKind: ConcurrencyKind,
priority: EventPriority
): MessageSubscribersBuilder<E, Listener<E>, Unit, Unit> = constructor(Unit) { filter, listener ->
subscribeAlways(coroutineContext, concurrencyKind, priority) {
val toString = this.message.content

View File

@ -34,7 +34,7 @@ import kotlin.reflect.KClass
@JvmSynthetic
public suspend inline fun <reified E : Event, R : Any> syncFromEvent(
timeoutMillis: Long = -1,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R?
): R {
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
public suspend inline fun <reified E : Event, R : Any> syncFromEventOrNull(
timeoutMillis: Long,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R?
): R? {
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(
timeoutMillis: Long,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R?
): Deferred<R?> {
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(
timeoutMillis: Long = -1,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
crossinline mapper: suspend E.(E) -> R?
): Deferred<R> {
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(
eventClass: KClass<E>,
coroutineScope: CoroutineScope,
priority: Listener.EventPriority,
priority: EventPriority,
crossinline mapper: suspend E.(E) -> R?
): R = suspendCancellableCoroutine { cont ->
coroutineScope.globalEventChannel().subscribe(eventClass, priority = priority) {

View File

@ -29,14 +29,14 @@ internal class Handler<in E : Event> internal constructor(
parentJob: Job?,
subscriberContext: CoroutineContext,
@JvmField val handler: suspend (E) -> ListeningStatus,
override val concurrencyKind: Listener.ConcurrencyKind,
override val priority: Listener.EventPriority
override val concurrencyKind: ConcurrencyKind,
override val priority: EventPriority
) : Listener<E>, CompletableJob by SupervisorJob(parentJob) { // avoid being cancelled on handling event
private val subscriberContext: CoroutineContext = subscriberContext + this // override Job.
val lock: Mutex? = when (concurrencyKind) {
Listener.ConcurrencyKind.LOCKED -> Mutex()
ConcurrencyKind.LOCKED -> Mutex()
else -> null
}
@ -78,14 +78,14 @@ internal object GlobalEventListeners {
init {
val map =
EnumMap<Listener.EventPriority, ConcurrentLinkedQueue<ListenerRegistry>>(Listener.EventPriority::class.java)
EnumMap<EventPriority, ConcurrentLinkedQueue<ListenerRegistry>>(EventPriority::class.java)
EventPriority.values().forEach {
map[it] = ConcurrentLinkedQueue()
}
ALL_LEVEL_REGISTRIES = map
}
operator fun get(priority: Listener.EventPriority): ConcurrentLinkedQueue<ListenerRegistry> =
operator fun get(priority: EventPriority): ConcurrentLinkedQueue<ListenerRegistry> =
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(
event: E
) {
for (p in Listener.EventPriority.prioritiesExcludedMonitor) {
for (p in EventPriority.prioritiesExcludedMonitor) {
GlobalEventListeners[p].forEach0 { registeredRegistry ->
if (event.isIntercepted) {
return
@ -113,14 +113,14 @@ internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired(
if (!registeredRegistry.type.isInstance(event)) return@forEach0
val listener = registeredRegistry.listener
when (listener.concurrencyKind) {
Listener.ConcurrencyKind.LOCKED -> {
ConcurrencyKind.LOCKED -> {
(listener as Handler).lock!!.withLock {
if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry)
}
}
}
Listener.ConcurrencyKind.CONCURRENT -> {
ConcurrencyKind.CONCURRENT -> {
if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry)
}
@ -137,14 +137,14 @@ internal suspend inline fun <E : AbstractEvent> callAndRemoveIfRequired(
val listener = registeredRegistry.listener
launch {
when (listener.concurrencyKind) {
Listener.ConcurrencyKind.LOCKED -> {
ConcurrencyKind.LOCKED -> {
(listener as Handler).lock!!.withLock {
if (listener.onEvent(event) == ListeningStatus.STOPPED) {
remove(registeredRegistry)
}
}
}
Listener.ConcurrencyKind.CONCURRENT -> {
ConcurrencyKind.CONCURRENT -> {
if (listener.onEvent(event) == ListeningStatus.STOPPED) {
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 许可证的约束, 可以在以下链接找到该许可证.
* 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.async
import net.mamoe.mirai.event.EventPriority
import net.mamoe.mirai.event.Listener
import net.mamoe.mirai.event.events.*
import net.mamoe.mirai.event.syncFromEvent
import net.mamoe.mirai.event.syncFromEventOrNull
@ -46,7 +45,7 @@ public fun MessageEvent.isContextIdenticalWith(another: MessageEvent): Boolean {
@JvmSynthetic
public suspend inline fun <reified P : MessageEvent> P.nextMessage(
timeoutMillis: Long = -1,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true }
): MessageChain {
return syncFromEvent<P, P>(timeoutMillis, priority) {
@ -68,7 +67,7 @@ public suspend inline fun <reified P : MessageEvent> P.nextMessage(
@JvmSynthetic
public suspend inline fun <reified P : MessageEvent> P.nextMessageOrNull(
timeoutMillis: Long,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true }
): MessageChain? {
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(
timeoutMillis: Long = -1,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true }
): Deferred<MessageChain> {
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(
timeoutMillis: Long,
coroutineContext: CoroutineContext = EmptyCoroutineContext,
priority: Listener.EventPriority = EventPriority.MONITOR,
priority: EventPriority = EventPriority.MONITOR,
noinline filter: suspend P.(P) -> Boolean = { true }
): Deferred<MessageChain?> {
require(timeoutMillis > 0) { "timeoutMillis must be > 0" }

View File

@ -52,7 +52,7 @@ class EventTests {
resetEventListeners()
var listeners = 0
val counter = AtomicInteger(0)
for (p in Listener.EventPriority.values()) {
for (p in EventPriority.values()) {
repeat(2333) {
listeners++
GlobalScope.globalEventChannel().subscribeAlways<ParentEvent> {
@ -78,7 +78,7 @@ class EventTests {
val registered = AtomicInteger()
coroutineScope {
println("Step 0")
for (priority in Listener.EventPriority.values()) {
for (priority in EventPriority.values()) {
launch {
repeat(5000) {
registered.getAndIncrement()
@ -216,7 +216,7 @@ class EventTests {
}
*/
fun resetEventListeners() {
for (p in Listener.EventPriority.values()) {
for (p in EventPriority.values()) {
GlobalEventListeners[p].clear()
}
}
@ -278,11 +278,11 @@ class EventTests {
step.step(1)
ListeningStatus.LISTENING
}
subscribe<PriorityTestEvent>(priority = Listener.EventPriority.HIGH) {
subscribe<PriorityTestEvent>(priority = EventPriority.HIGH) {
step.step(0)
ListeningStatus.LISTENING
}
subscribe<PriorityTestEvent>(priority = Listener.EventPriority.LOW) {
subscribe<PriorityTestEvent>(priority = EventPriority.LOW) {
step.step(3)
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 许可证的约束, 可以在以下链接找到该许可证.
* 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()
@Suppress("unused")
@EventHandler(Listener.EventPriority.HIGHEST)
@EventHandler(EventPriority.HIGHEST)
private suspend fun TestEvent.`suspend receiver param Unit`(event: TestEvent) {
intercept()
called.getAndIncrement()
}
@EventHandler(Listener.EventPriority.MONITOR)
@EventHandler(EventPriority.MONITOR)
@Suppress("unused")
private fun TestEvent.`receiver param LS`(event: TestEvent): ListeningStatus {
called.getAndIncrement()

View File

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

View File

@ -479,7 +479,7 @@ internal class QQAndroidBotNetworkHandler(coroutineContext: CoroutineContext, bo
init {
@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() }
}
supervisor.invokeOnCompletion { listener.cancel() }