From 141b5a4e2f3c77d7f1a0f6a2a02db755418a2b9f Mon Sep 17 00:00:00 2001
From: Him188 <Him188@mamoe.net>
Date: Sun, 27 Oct 2019 03:48:45 +0800
Subject: [PATCH] Adjust function visibility and enhance efficiency

---
 .../net.mamoe.mirai/event/Subscribers.kt      | 66 ++++++++++++-------
 .../event/internal/InternalEventListeners.kt  | 19 +++---
 2 files changed, 52 insertions(+), 33 deletions(-)

diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt
index f303fd3ed..d856ffefb 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/Subscribers.kt
@@ -3,6 +3,7 @@
 package net.mamoe.mirai.event
 
 import net.mamoe.mirai.event.internal.Handler
+import net.mamoe.mirai.event.internal.Listener
 import net.mamoe.mirai.event.internal.subscribeInternal
 import kotlin.reflect.KClass
 
@@ -43,26 +44,41 @@ suspend inline fun <reified E : Event> subscribeWhileNull(noinline listener: sus
 
 // region KClass 的扩展方法 (不推荐)
 
-suspend fun <E : Event> KClass<E>.subscribe(handler: suspend (E) -> ListeningStatus) = this.subscribeInternal(Handler(handler))
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribe(handler: suspend (E) -> ListeningStatus) = this.subscribeInternal(Handler(handler))
 
-suspend fun <E : Event> KClass<E>.subscribeAlways(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.LISTENING })
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeAlways(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.LISTENING })
 
-suspend fun <E : Event> KClass<E>.subscribeOnce(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.STOPPED })
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeOnce(listener: suspend (E) -> Unit) = this.subscribeInternal(Handler { listener(it); ListeningStatus.STOPPED })
 
-suspend fun <E : Event, T> KClass<E>.subscribeUntil(valueIfStop: T, listener: suspend (E) -> T) =
+@PublishedApi
+internal suspend fun <E : Event, T> KClass<E>.subscribeUntil(valueIfStop: T, listener: suspend (E) -> T) =
     subscribeInternal(Handler { if (listener(it) === valueIfStop) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
 
-suspend fun <E : Event> KClass<E>.subscribeUntilFalse(listener: suspend (E) -> Boolean) = subscribeUntil(false, listener)
-suspend fun <E : Event> KClass<E>.subscribeUntilTrue(listener: suspend (E) -> Boolean) = subscribeUntil(true, listener)
-suspend fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> Any?) = subscribeUntil(null, listener)
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeUntilFalse(listener: suspend (E) -> Boolean) = subscribeUntil(false, listener)
+
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeUntilTrue(listener: suspend (E) -> Boolean) = subscribeUntil(true, listener)
+
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeUntilNull(listener: suspend (E) -> Any?) = subscribeUntil(null, listener)
 
 
-suspend fun <E : Event, T> KClass<E>.subscribeWhile(valueIfContinue: T, listener: suspend (E) -> T) =
+@PublishedApi
+internal suspend fun <E : Event, T> KClass<E>.subscribeWhile(valueIfContinue: T, listener: suspend (E) -> T) =
     subscribeInternal(Handler { if (listener(it) !== valueIfContinue) ListeningStatus.STOPPED else ListeningStatus.LISTENING })
 
-suspend fun <E : Event> KClass<E>.subscribeWhileFalse(listener: suspend (E) -> Boolean) = subscribeWhile(false, listener)
-suspend fun <E : Event> KClass<E>.subscribeWhileTrue(listener: suspend (E) -> Boolean) = subscribeWhile(true, listener)
-suspend fun <E : Event> KClass<E>.subscribeWhileNull(listener: suspend (E) -> Any?) = subscribeWhile(null, listener)
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeWhileFalse(listener: suspend (E) -> Boolean) = subscribeWhile(false, listener)
+
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeWhileTrue(listener: suspend (E) -> Boolean) = subscribeWhile(true, listener)
+
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeWhileNull(listener: suspend (E) -> Any?) = subscribeWhile(null, listener)
 
 // endregion
 
@@ -73,7 +89,8 @@ suspend fun <E : Event> KClass<E>.subscribeWhileNull(listener: suspend (E) -> An
  * @see ListenerBuilder
  */
 @ListenersBuilderDsl
-suspend fun <E : Event> KClass<E>.subscribeAll(listeners: suspend ListenerBuilder<E>.() -> Unit) {
+@PublishedApi
+internal suspend fun <E : Event> KClass<E>.subscribeAll(listeners: suspend ListenerBuilder<E>.() -> Unit) {
     with(ListenerBuilder<E> { this.subscribeInternal(it) }) {
         listeners()
     }
@@ -105,27 +122,28 @@ suspend inline fun <reified E : Event> subscribeAll(noinline listeners: suspend
 @ListenersBuilderDsl
 @Suppress("MemberVisibilityCanBePrivate", "unused")
 inline class ListenerBuilder<out E : Event>(
-    private val handlerConsumer: suspend (Handler<in E>) -> Unit
+    @PublishedApi
+    internal inline val handlerConsumer: suspend (Listener<E>) -> Unit
 ) {
-    suspend fun handler(listener: suspend (E) -> ListeningStatus) {
+    suspend inline fun handler(noinline listener: suspend (E) -> ListeningStatus) {
         handlerConsumer(Handler(listener))
     }
 
-    suspend fun always(listener: suspend (E) -> Unit) = handler { listener(it); ListeningStatus.LISTENING }
+    suspend inline fun always(noinline listener: suspend (E) -> Unit) = handler { listener(it); ListeningStatus.LISTENING }
 
-    suspend fun <T> until(until: T, listener: suspend (E) -> T) = handler { if (listener(it) === until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
-    suspend fun untilFalse(listener: suspend (E) -> Boolean) = until(false, listener)
-    suspend fun untilTrue(listener: suspend (E) -> Boolean) = until(true, listener)
-    suspend fun untilNull(listener: suspend (E) -> Any?) = until(null, listener)
+    suspend inline fun <T> until(until: T, noinline listener: suspend (E) -> T) = handler { if (listener(it) === until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
+    suspend inline fun untilFalse(noinline listener: suspend (E) -> Boolean) = until(false, listener)
+    suspend inline fun untilTrue(noinline listener: suspend (E) -> Boolean) = until(true, listener)
+    suspend inline fun untilNull(noinline listener: suspend (E) -> Any?) = until(null, listener)
 
 
-    suspend fun <T> `while`(until: T, listener: suspend (E) -> T) = handler { if (listener(it) !== until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
-    suspend fun whileFalse(listener: suspend (E) -> Boolean) = `while`(false, listener)
-    suspend fun whileTrue(listener: suspend (E) -> Boolean) = `while`(true, listener)
-    suspend fun whileNull(listener: suspend (E) -> Any?) = `while`(null, listener)
+    suspend inline fun <T> `while`(until: T, noinline listener: suspend (E) -> T) = handler { if (listener(it) !== until) ListeningStatus.STOPPED else ListeningStatus.LISTENING }
+    suspend inline fun whileFalse(noinline listener: suspend (E) -> Boolean) = `while`(false, listener)
+    suspend inline fun whileTrue(noinline listener: suspend (E) -> Boolean) = `while`(true, listener)
+    suspend inline fun whileNull(noinline listener: suspend (E) -> Any?) = `while`(null, listener)
 
 
-    suspend fun once(block: suspend (E) -> Unit) = handler { block(it); ListeningStatus.STOPPED }
+    suspend inline fun once(noinline listener: suspend (E) -> Unit) = handler { listener(it); ListeningStatus.STOPPED }
 }
 
 @DslMarker
diff --git a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
index 7f4069dee..9e3e450a1 100644
--- a/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
+++ b/mirai-core/src/commonMain/kotlin/net.mamoe.mirai/event/internal/InternalEventListeners.kt
@@ -9,6 +9,7 @@ import net.mamoe.mirai.event.EventScope
 import net.mamoe.mirai.event.ListeningStatus
 import net.mamoe.mirai.event.events.BotEvent
 import net.mamoe.mirai.utils.internal.inlinedRemoveIf
+import kotlin.jvm.JvmField
 import kotlin.reflect.KClass
 
 /**
@@ -38,9 +39,11 @@ internal suspend fun <E : Event> KClass<E>.subscribeInternal(listener: Listener<
         //启动协程并等待正在进行的广播结束, 然后将缓存转移到主监听者列表
         //启动后的协程马上就会因为锁而被挂起
         mainMutex.withLock {
-            if (cache.size != 0) {
-                addAll(cache)
-                cache.clear()
+            cacheMutex.withLock {
+                if (cache.size != 0) {
+                    addAll(cache)
+                    cache.clear()
+                }
             }
         }
     }
@@ -55,11 +58,8 @@ sealed class Listener<in E : Event> {
     abstract suspend fun onEvent(event: E): ListeningStatus
 }
 
-/**
- * Lambda 监听器.
- * 不推荐直接使用该类
- */
-class Handler<E : Event>(val handler: suspend (E) -> ListeningStatus) : Listener<E>() {
+@PublishedApi
+internal class Handler<E : Event>(@JvmField val handler: suspend (E) -> ListeningStatus) : Listener<E>() {
     override suspend fun onEvent(event: E): ListeningStatus = handler.invoke(event)
 }
 
@@ -68,7 +68,8 @@ class Handler<E : Event>(val handler: suspend (E) -> ListeningStatus) : Listener
  * 所有的非 [BotEvent] 的事件都不会被处理
  * 所有的 [BotEvent.bot] `!==` `bot` 的事件都不会被处理
  */
-class HandlerWithBot<E : Event>(val bot: Bot, val handler: suspend Bot.(E) -> ListeningStatus) : Listener<E>() {
+@PublishedApi
+internal class HandlerWithBot<E : Event>(val bot: Bot, @JvmField val handler: suspend Bot.(E) -> ListeningStatus) : Listener<E>() {
     override suspend fun onEvent(event: E): ListeningStatus = with(bot) {
         if (event !is BotEvent || event.bot !== this) {
             return ListeningStatus.LISTENING