Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* Copyright 2025 Apollointhehouse
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

package me.apollointhehouse.raywire.internal

import me.apollointhehouse.raywire.api.Event

internal fun interface EventInvoker {
operator fun invoke(target: Any, event: Event)
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import me.apollointhehouse.raywire.api.Bus
import me.apollointhehouse.raywire.api.Cancellable
import me.apollointhehouse.raywire.api.Event
import me.apollointhehouse.raywire.api.EventHandler
import java.lang.invoke.LambdaMetafactory
import java.lang.invoke.MethodHandles
import java.lang.invoke.MethodType
import java.lang.ref.WeakReference
import java.lang.reflect.Method
import java.lang.reflect.Modifier
Expand Down Expand Up @@ -54,7 +57,7 @@ internal class EventManager : Bus {
@Suppress("UNCHECKED_CAST")
val eventClass = method.parameterTypes[0] as Class<out Event>
val priority = method.getAnnotation(EventHandler::class.java).priority
val handler = Handler(WeakReference(obj), method, priority)
val handler = Handler(WeakReference(obj), createInvoker(method), priority)

val list = methodCache.getOrPut(eventClass) { mutableListOf() }

Expand Down Expand Up @@ -102,7 +105,7 @@ internal class EventManager : Bus {
if (cancellable?.cancelled == true) break
try {
val target = handler.target.get() ?: continue
handler.method.invoke(target, event)
handler.invoker(target, event)
} catch (e: Exception) {
LOGGER.error("Failed to invoke handler for event: ${event::class.simpleName}", e)
}
Expand Down Expand Up @@ -174,4 +177,30 @@ internal class EventManager : Bus {

return result
}
private fun createInvoker(method: Method): EventInvoker {
return try {
val lookup = MethodHandles.lookup()
val handle = lookup.unreflect(method)
val samMethodType = MethodType.methodType(Void.TYPE, Any::class.java, Event::class.java)
val invokedType = MethodType.methodType(EventInvoker::class.java)
val implMethodType = handle.type()

val callSite = LambdaMetafactory.metafactory(
lookup,
"invoke",
invokedType,
samMethodType,
handle,
implMethodType
)

val factory = callSite.target
factory.invokeExact() as EventInvoker
} catch (t: Throwable) {
LOGGER.error("Failed to create lambda invoker for ${method.declaringClass.name}#${method.name}, falling back to reflection.", t)
EventInvoker { target, event ->
method.invoke(target, event)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,5 @@
package me.apollointhehouse.raywire.internal

import java.lang.ref.WeakReference
import java.lang.reflect.Method

internal data class Handler(val target: WeakReference<Any>, val method: Method, val priority: Int)
internal data class Handler(val target: WeakReference<Any>, val invoker: EventInvoker, val priority: Int)
Loading