Archived
0

Add passthrough for exceptions

This commit is contained in:
Dico Karssiens
2018-07-30 13:57:39 +01:00
parent ee287253d6
commit 48da05c9e8
2 changed files with 28 additions and 8 deletions

View File

@@ -31,7 +31,7 @@ class ParcelsPlugin : JavaPlugin() {
lateinit var entityTracker: ParcelEntityTracker; private set lateinit var entityTracker: ParcelEntityTracker; private set
private var listeners: ParcelListeners? = null private var listeners: ParcelListeners? = null
private var cmdDispatcher: ICommandDispatcher? = null private var cmdDispatcher: ICommandDispatcher? = null
val worktimeLimiter: WorktimeLimiter by lazy { TickWorktimeLimiter(this, options) } val worktimeLimiter: WorktimeLimiter by lazy { TickWorktimeLimiter(this, options.tickWorktime) }
override fun onEnable() { override fun onEnable() {
plogger.info("Debug enabled: ${plogger.isDebugEnabled}") plogger.info("Debug enabled: ${plogger.isDebugEnabled}")

View File

@@ -6,6 +6,7 @@ import org.bukkit.scheduler.BukkitTask
import java.lang.System.currentTimeMillis import java.lang.System.currentTimeMillis
import java.util.* import java.util.*
import java.util.concurrent.Executor import java.util.concurrent.Executor
import java.util.logging.Level
import kotlin.coroutines.experimental.Continuation import kotlin.coroutines.experimental.Continuation
import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED import kotlin.coroutines.experimental.intrinsics.COROUTINE_SUSPENDED
import kotlin.coroutines.experimental.intrinsics.suspendCoroutineUninterceptedOrReturn import kotlin.coroutines.experimental.intrinsics.suspendCoroutineUninterceptedOrReturn
@@ -46,6 +47,12 @@ interface Worker : Timed {
*/ */
val isComplete: Boolean val isComplete: Boolean
/**
* If an exception was thrown during the execution of this task,
* returns that exception. Returns null otherwise.
*/
val completionException: Throwable?
/** /**
* A value indicating the progress of this worker, in the range 0.0 <= progress <= 1.0 * A value indicating the progress of this worker, in the range 0.0 <= progress <= 1.0
* with no guarantees to its accuracy. May be null. * with no guarantees to its accuracy. May be null.
@@ -104,7 +111,7 @@ class TickWorktimeLimiter(private val plugin: Plugin, var options: TickWorktimeO
override val workers: List<Worker> = _workers override val workers: List<Worker> = _workers
override fun submit(task: TimeLimitedTask): Worker { override fun submit(task: TimeLimitedTask): Worker {
val worker: WorkerContinuation = WorkerImpl(dispatcher, task) val worker: WorkerContinuation = WorkerImpl(plugin, dispatcher, task)
_workers.addFirst(worker) _workers.addFirst(worker)
if (bukkitTask == null) bukkitTask = plugin.server.scheduler.runTaskTimer(plugin, ::tickJobs, 0, options.tickInterval.toLong()) if (bukkitTask == null) bukkitTask = plugin.server.scheduler.runTaskTimer(plugin, ::tickJobs, 0, options.tickInterval.toLong())
return worker return worker
@@ -122,7 +129,7 @@ class TickWorktimeLimiter(private val plugin: Plugin, var options: TickWorktimeO
val timeLeft = options.workTime - timeElapsed val timeLeft = options.workTime - timeElapsed
if (timeLeft <= 0) return if (timeLeft <= 0) return
val count = iterator.nextIndex() val count = workers.size - iterator.nextIndex()
val timePerJob = (timeLeft + count - 1) / count val timePerJob = (timeLeft + count - 1) / count
val worker = iterator.next() val worker = iterator.next()
val completed = worker.resume(timePerJob) val completed = worker.resume(timePerJob)
@@ -139,7 +146,8 @@ class TickWorktimeLimiter(private val plugin: Plugin, var options: TickWorktimeO
} }
private class WorkerImpl(val dispatcher: CoroutineDispatcher, private class WorkerImpl(val plugin: Plugin,
val dispatcher: CoroutineDispatcher,
val task: TimeLimitedTask) : WorkerContinuation { val task: TimeLimitedTask) : WorkerContinuation {
override var job: Job? = null; private set override var job: Job? = null; private set
@@ -151,6 +159,8 @@ private class WorkerImpl(val dispatcher: CoroutineDispatcher,
override val isComplete get() = job?.isCompleted == true override val isComplete get() = job?.isCompleted == true
override var completionException: Throwable? = null; private set
override var progress: Double? = null; private set override var progress: Double? = null; private set
private var startTimeOrElapsedTime: Long = 0L // startTime before completed, elapsed time otherwise private var startTimeOrElapsedTime: Long = 0L // startTime before completed, elapsed time otherwise
@@ -165,7 +175,13 @@ private class WorkerImpl(val dispatcher: CoroutineDispatcher,
this.job?.let { throw IllegalStateException() } this.job?.let { throw IllegalStateException() }
this.job = job this.job = job
startTimeOrElapsedTime = System.currentTimeMillis() startTimeOrElapsedTime = System.currentTimeMillis()
job.invokeOnCompletion { job.invokeOnCompletion { exception ->
// report any error that occurred
completionException = exception?.also {
if (it !is CancellationException)
plugin.logger.log(Level.SEVERE, "TimeLimitedTask for plugin ${plugin.name} generated an exception", it)
}
// convert to elapsed time here // convert to elapsed time here
startTimeOrElapsedTime = System.currentTimeMillis() - startTimeOrElapsedTime startTimeOrElapsedTime = System.currentTimeMillis() - startTimeOrElapsedTime
onCompleted?.let { it(1.0, elapsedTime) } onCompleted?.let { it(1.0, elapsedTime) }
@@ -219,9 +235,13 @@ private class WorkerImpl(val dispatcher: CoroutineDispatcher,
throw IllegalStateException() throw IllegalStateException()
} }
launch(context = dispatcher, start = CoroutineStart.UNDISPATCHED) { try {
initJob(job = kotlin.coroutines.experimental.coroutineContext[Job]!!) launch(context = dispatcher, start = CoroutineStart.UNDISPATCHED) {
task() initJob(job = kotlin.coroutines.experimental.coroutineContext[Job]!!)
task()
}
} catch (t: Throwable) {
// do nothing: handled by job.invokeOnCompletion()
} }
return continuation == null return continuation == null