aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/me/bush/illnamethislater/EventBus.kt
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/me/bush/illnamethislater/EventBus.kt')
-rw-r--r--src/main/kotlin/me/bush/illnamethislater/EventBus.kt95
1 files changed, 49 insertions, 46 deletions
diff --git a/src/main/kotlin/me/bush/illnamethislater/EventBus.kt b/src/main/kotlin/me/bush/illnamethislater/EventBus.kt
index f35b65d..4de6bc5 100644
--- a/src/main/kotlin/me/bush/illnamethislater/EventBus.kt
+++ b/src/main/kotlin/me/bush/illnamethislater/EventBus.kt
@@ -2,81 +2,84 @@ package me.bush.illnamethislater
import org.apache.logging.log4j.LogManager
import org.apache.logging.log4j.Logger
-import java.util.UUID
-import java.util.concurrent.atomic.AtomicLong
import kotlin.reflect.KClass
-import kotlin.reflect.full.findAnnotation
/**
+ * [A simple event dispatcher](http://github.com/therealbush/eventbus-kotlin)
+ *
* @author bush
- * @since 3/13/2022
+ * @since 1.0.0
*/
-class EventBus(private val logger: Logger = LogManager.getLogger(), private val strict: Boolean = true) {
- private val listeners = hashMapOf<KClass<*>, MutableList<Listener>>()
- private val subscribers = hashSetOf<Any>()
-
- // TODO: 3/26/2022 coroutine shit idk
+class EventBus(private val logger: Logger = LogManager.getLogger()) {
+ private val listeners = hashMapOf<KClass<*>, ListenerList>()
+ private val subscribers = mutableSetOf<Any>()
/**
* blah blah annotation properties override listener properties
*/
- fun subscribe(subscriber: Any) {
- if (subscribers.add(subscriber)) {
- subscriber::class.allMembers.filterReturnType<Listener>().forEach { property ->
- register(property.handleCall(subscriber).apply {
- // If the annotation is present, update listener settings from it
- // If it is not, and we are in strict mode, continue to the next property
- property.findAnnotation<EventListener>()?.let {
- priority = it.priority
- receiveCancelled = it.receiveCancelled
- } ?: if (strict) return@forEach
- }, subscriber)
+ infix fun subscribe(subscriber: Any): Boolean {
+ return if (subscriber in subscribers) false
+ else runCatching {
+ subscriber::class.listeners.forEach {
+ register(it.handleCall(subscriber), subscriber)
}
+ true
+ }.getOrElse {
+ logger.error("Unable to register listeners for subscriber $subscriber", it)
+ false
}
}
/**
+ * Registers a listener (which may not belong to any subscriber) to this [EventBus]. If no object
+ * is given, a key will be returned which can be used in [unsubscribe] to remove the listener.
*
+ * The
*/
- fun register(listener: Listener, subscriber: Any = ListenerKey()): Any {
- putListener(listener.also { it.subscriber = subscriber })
+ fun register(listener: Listener, subscriber: Any = Any()): Any {
+ listeners.getOrPut(listener.type) { ListenerList() }
+ .add(listener.also { it.subscriber = subscriber })
+ subscribers += subscriber
return subscriber
}
/**
- * Puts a listener into its respective list and sorts the list.
+ *
*/
- private fun putListener(listener: Listener) {
- listeners.getOrPut(listener.type) { mutableListOf() }.run {
- add(listener)
- sortBy(Listener::priority)
+ // doc
+ infix fun unsubscribe(subscriber: Any) = subscribers.remove(subscriber).apply {
+ if (this) listeners.entries.removeIf {
+ it.value.removeFrom(subscriber)
+ it.value.isEmpty
}
}
/**
- *
+ * Posts an event.
*/
- fun unsubscribe(subscriber: Any) {
- if (subscribers.remove(subscriber)) {
- listeners.values.forEach { it.removeIf(subscriber::equals) }
- }
- }
+ // doc
+ infix fun post(event: Any) = listeners[event::class]?.post(event)
/**
- * ur mom
+ * Logs the subscriber count, total listener count, and listener count
+ * for every event type with at least one subscriber to [logger].
+ * Per-event counts are sorted from greatest to least listeners.
+ * ```
+ * Subscribers: 5
+ * Listeners: 8 sequential, 4 parallel
+ * SomeInnerClass: 4, 2
+ * OtherEvent: 3, 1
+ * String: 1, 1
*/
- fun post(event: Any) = listeners[event::class].let { list ->
- if (list == null || list.isEmpty()) false
- else if (event is Event) {
- list.forEach {
- if (!event.cancelled || it.receiveCancelled) {
- it.listener(event)
- }
+ fun debugInfo() {
+ logger.info(StringBuilder().apply {
+ append("\nSubscribers: ${subscribers.size}")
+ val sequential = listeners.values.sumOf { it.sequential.size }
+ val parallel = listeners.values.sumOf { it.parallel.size }
+ append("\nListeners: $sequential sequential, $parallel parallel")
+ listeners.entries.sortedByDescending { it.value.sequential.size + it.value.parallel.size }.forEach {
+ append("\n${it.key.simpleName}: ${it.value.sequential.size}, ${it.value.parallel.size}")
}
- event.cancelled
- } else {
- list.forEach { it.listener(event) }
- false
- }
+ }.toString())
}
}