From 95a6eef6df91a605ec4b23724775f8f1b90eb194 Mon Sep 17 00:00:00 2001 From: F0Xde Date: Sun, 18 Oct 2020 11:16:03 +0200 Subject: [PATCH 1/4] Use reified type parameter for executeCatching; sync / async handlers The unsafe cast before would throw an exception if any other generic parameter than `Exception` was used without passing the class reference explicitly. It can now also be specified whether the exception handler is to be executed sync or async, defaulting to sync. --- .../kspigot/runnables/ChainableRunnables.kt | 70 ++++++++++++------- .../kspigot/runnables/KSpigotRunnables.kt | 8 +++ 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt index 8aac2820..038bf3ab 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt @@ -2,8 +2,6 @@ package net.axay.kspigot.runnables -import net.axay.kspigot.main.KSpigotMainInstance -import org.bukkit.Bukkit import kotlin.reflect.KClass abstract class ChainedRunnablePart( @@ -16,13 +14,33 @@ abstract class ChainedRunnablePart( abstract fun execute() - abstract fun executeCatching( - @Suppress("UNCHECKED_CAST") exceptionClass: KClass = Exception::class as KClass, - exceptionHandler: ((E) -> Unit)? = null + /** + * Begins execution of this chained runnable, catching any exception of + * type [E] and passing it to the optional [exceptionHandler]. + * + * @param exceptionSync whether the exception handler should be executed + * synchronously or asynchronously, defaults to `true` (Note that usage of + * any Spigot API functions requires it to be sync) + */ + inline fun executeCatching( + noinline exceptionHandler: ((E) -> Unit)? = null, + exceptionSync: Boolean = true + ) { + executeCatchingImpl(E::class, exceptionHandler, exceptionSync) + } + + /** + * Has to be public for use in inline function [executeCatching], not + * intended to be used directly. + */ + abstract fun executeCatchingImpl( + exceptionClass: KClass, + exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean ) protected fun start(data: T) { - this.run { + runTask(sync) { val result = invoke(data) next?.start(result) } @@ -31,30 +49,28 @@ abstract class ChainedRunnablePart( protected fun startCatching( data: T, exceptionClass: KClass, - exceptionHandler: ((E) -> Unit)? + exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean ) { - this.run { + runTask(sync) { val result = try { invoke(data) } catch (e: Exception) { if (exceptionClass.isInstance(e)) { @Suppress("UNCHECKED_CAST") - exceptionHandler?.invoke(e as E) - null + if (sync == exceptionSync) { + exceptionHandler?.invoke(e as E) + } else if (exceptionHandler != null) { + runTask(exceptionSync) { + exceptionHandler.invoke(e as E) + } + } + return@runTask } else throw e } - if (result != null) - next?.startCatching(result, exceptionClass, exceptionHandler) + next?.startCatching(result, exceptionClass, exceptionHandler, exceptionSync) } } - - private fun run(realRunnable: () -> Unit) { - if (sync) - Bukkit.getScheduler().runTask(KSpigotMainInstance, realRunnable) - else - Bukkit.getScheduler().runTaskAsynchronously(KSpigotMainInstance, realRunnable) - } - } class ChainedRunnablePartFirst( @@ -65,8 +81,11 @@ class ChainedRunnablePartFirst( override fun execute() = start(Unit) - override fun executeCatching(exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?) - = startCatching(Unit, exceptionClass, exceptionHandler) + override fun executeCatchingImpl( + exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean + ) = + startCatching(Unit, exceptionClass, exceptionHandler, exceptionSync) override fun invoke(data: Unit) = runnable.invoke() @@ -81,8 +100,11 @@ class ChainedRunnablePartThen( override fun execute() = previous.execute() - override fun executeCatching(exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?) - = previous.executeCatching(exceptionClass, exceptionHandler) + override fun executeCatchingImpl( + exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?, + exceptionSync: Boolean + ) = + previous.executeCatchingImpl(exceptionClass, exceptionHandler, exceptionSync) override fun invoke(data: T) = runnable.invoke(data) diff --git a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt index 8a3ebb10..cedf07fe 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt @@ -104,6 +104,14 @@ fun task( } +fun runTask(sync: Boolean, runnable: () -> Unit) { + if (sync) { + sync(runnable) + } else { + async(runnable) + } +} + /** * Starts a synchronous task. */ From c872a94fb20dbe24eebfac9e56020f2b83f7ca63 Mon Sep 17 00:00:00 2001 From: F0Xde Date: Sun, 18 Oct 2020 11:30:13 +0200 Subject: [PATCH 2/4] Make exception handler last argument --- .../kspigot/runnables/ChainableRunnables.kt | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt index 038bf3ab..5634350c 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt @@ -23,10 +23,10 @@ abstract class ChainedRunnablePart( * any Spigot API functions requires it to be sync) */ inline fun executeCatching( - noinline exceptionHandler: ((E) -> Unit)? = null, - exceptionSync: Boolean = true + exceptionSync: Boolean = true, + noinline exceptionHandler: ((E) -> Unit)? = null ) { - executeCatchingImpl(E::class, exceptionHandler, exceptionSync) + executeCatchingImpl(E::class, exceptionSync, exceptionHandler) } /** @@ -35,8 +35,8 @@ abstract class ChainedRunnablePart( */ abstract fun executeCatchingImpl( exceptionClass: KClass, + exceptionSync: Boolean, exceptionHandler: ((E) -> Unit)?, - exceptionSync: Boolean ) protected fun start(data: T) { @@ -49,8 +49,8 @@ abstract class ChainedRunnablePart( protected fun startCatching( data: T, exceptionClass: KClass, + exceptionSync: Boolean, exceptionHandler: ((E) -> Unit)?, - exceptionSync: Boolean ) { runTask(sync) { val result = try { @@ -68,7 +68,7 @@ abstract class ChainedRunnablePart( return@runTask } else throw e } - next?.startCatching(result, exceptionClass, exceptionHandler, exceptionSync) + next?.startCatching(result, exceptionClass, exceptionSync, exceptionHandler) } } } @@ -82,10 +82,11 @@ class ChainedRunnablePartFirst( = start(Unit) override fun executeCatchingImpl( - exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?, - exceptionSync: Boolean + exceptionClass: KClass, + exceptionSync: Boolean, + exceptionHandler: ((E) -> Unit)? ) = - startCatching(Unit, exceptionClass, exceptionHandler, exceptionSync) + startCatching(Unit, exceptionClass, exceptionSync, exceptionHandler) override fun invoke(data: Unit) = runnable.invoke() @@ -101,10 +102,11 @@ class ChainedRunnablePartThen( = previous.execute() override fun executeCatchingImpl( - exceptionClass: KClass, exceptionHandler: ((E) -> Unit)?, - exceptionSync: Boolean + exceptionClass: KClass, + exceptionSync: Boolean, + exceptionHandler: ((E) -> Unit)? ) = - previous.executeCatchingImpl(exceptionClass, exceptionHandler, exceptionSync) + previous.executeCatchingImpl(exceptionClass, exceptionSync, exceptionHandler) override fun invoke(data: T) = runnable.invoke(data) From dcdb817a7c92ebe6b0da371b78f9dd0faa3b7c08 Mon Sep 17 00:00:00 2001 From: bluefireoly Date: Sun, 18 Oct 2020 16:53:10 +0200 Subject: [PATCH 3/4] Changed runTask to bukkitRun Changed the runTask method to bukkitRun and added documentation --- .../net/axay/kspigot/runnables/ChainableRunnables.kt | 8 ++++---- .../kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt | 6 +++++- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt index 5634350c..80b06464 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt @@ -40,7 +40,7 @@ abstract class ChainedRunnablePart( ) protected fun start(data: T) { - runTask(sync) { + bukkitRun(sync) { val result = invoke(data) next?.start(result) } @@ -52,7 +52,7 @@ abstract class ChainedRunnablePart( exceptionSync: Boolean, exceptionHandler: ((E) -> Unit)?, ) { - runTask(sync) { + bukkitRun(sync) { val result = try { invoke(data) } catch (e: Exception) { @@ -61,11 +61,11 @@ abstract class ChainedRunnablePart( if (sync == exceptionSync) { exceptionHandler?.invoke(e as E) } else if (exceptionHandler != null) { - runTask(exceptionSync) { + bukkitRun(exceptionSync) { exceptionHandler.invoke(e as E) } } - return@runTask + return@bukkitRun } else throw e } next?.startCatching(result, exceptionClass, exceptionSync, exceptionHandler) diff --git a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt index cedf07fe..b9f51f1e 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/KSpigotRunnables.kt @@ -104,7 +104,11 @@ fun task( } -fun runTask(sync: Boolean, runnable: () -> Unit) { +/** + * Executes the given [runnable] either + * sync or async (specified by the [sync] parameter). + */ +fun bukkitRun(sync: Boolean, runnable: () -> Unit) { if (sync) { sync(runnable) } else { From f606fac7a4851ed841df715ef0d20ea9ee257c68 Mon Sep 17 00:00:00 2001 From: bluefireoly Date: Sun, 18 Oct 2020 17:16:04 +0200 Subject: [PATCH 4/4] Reformatted code and added documentation --- .../net/axay/kspigot/runnables/ChainableRunnables.kt | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt index 80b06464..3f3f9c4f 100644 --- a/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt +++ b/src/main/kotlin/net/axay/kspigot/runnables/ChainableRunnables.kt @@ -12,6 +12,9 @@ abstract class ChainedRunnablePart( protected abstract fun invoke(data: T): R + /** + * Begins execution of this chained runnable. + */ abstract fun execute() /** @@ -71,6 +74,7 @@ abstract class ChainedRunnablePart( next?.startCatching(result, exceptionClass, exceptionSync, exceptionHandler) } } + } class ChainedRunnablePartFirst( @@ -85,8 +89,7 @@ class ChainedRunnablePartFirst( exceptionClass: KClass, exceptionSync: Boolean, exceptionHandler: ((E) -> Unit)? - ) = - startCatching(Unit, exceptionClass, exceptionSync, exceptionHandler) + ) = startCatching(Unit, exceptionClass, exceptionSync, exceptionHandler) override fun invoke(data: Unit) = runnable.invoke() @@ -105,8 +108,7 @@ class ChainedRunnablePartThen( exceptionClass: KClass, exceptionSync: Boolean, exceptionHandler: ((E) -> Unit)? - ) = - previous.executeCatchingImpl(exceptionClass, exceptionSync, exceptionHandler) + ) = previous.executeCatchingImpl(exceptionClass, exceptionSync, exceptionHandler) override fun invoke(data: T) = runnable.invoke(data)