mirror of
https://github.com/corda/corda.git
synced 2025-04-08 11:54:44 +00:00
Merged in aslemmer-fix-clockutils-race (pull request #328)
fix clockutils race
This commit is contained in:
commit
220b3f9043
@ -37,7 +37,7 @@ abstract class MutableClock : Clock() {
|
||||
private val _version = AtomicLong(0L)
|
||||
|
||||
/**
|
||||
* This tracks how many direct mutations of "now" have occured for this [Clock], but not the passage of time.
|
||||
* This tracks how many direct mutations of "now" have occurred for this [Clock], but not the passage of time.
|
||||
*
|
||||
* It starts at zero, and increments by one per mutation.
|
||||
*/
|
||||
@ -79,22 +79,22 @@ abstract class MutableClock : Clock() {
|
||||
*
|
||||
* @throws InterruptedException if interrupted by something other than a [MutableClock].
|
||||
*/
|
||||
@Suppress("UNUSED_VALUE") // This is here due to the compiler thinking version is not used
|
||||
@Suspendable
|
||||
private fun Clock.doInterruptibly(runnable: SuspendableRunnable) {
|
||||
var version = 0L
|
||||
var subscription: Subscription? = null
|
||||
var interruptedByMutation = false
|
||||
try {
|
||||
if (this is MutableClock) {
|
||||
version = this.mutationCount
|
||||
val strand = Strand.currentStrand()
|
||||
subscription = this.mutations.subscribe { strand.interrupt() }
|
||||
subscription = this.mutations.subscribe {
|
||||
interruptedByMutation = true
|
||||
strand.interrupt()
|
||||
}
|
||||
}
|
||||
runnable.run()
|
||||
} catch(e: InterruptedException) {
|
||||
// If clock has not mutated, then re-throw
|
||||
val newVersion = if (this is MutableClock) this.mutationCount else version
|
||||
if (newVersion == version) {
|
||||
if (!interruptedByMutation) {
|
||||
throw e
|
||||
}
|
||||
} finally {
|
||||
|
@ -16,6 +16,7 @@ import java.util.concurrent.ExecutorService
|
||||
import java.util.concurrent.Executors
|
||||
import kotlin.test.assertFalse
|
||||
import kotlin.test.assertTrue
|
||||
import kotlin.test.fail
|
||||
|
||||
class ClockUtilsTest {
|
||||
|
||||
@ -112,6 +113,27 @@ class ClockUtilsTest {
|
||||
assertFalse(testClock.awaitWithDeadline(advancedClock.instant(), future), "Should have reached deadline")
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `test external interrupt of a clock future`() {
|
||||
val mainStrand = Strand.currentStrand()
|
||||
executor.execute @Suspendable {
|
||||
// Wait until main thread is waiting
|
||||
while (mainStrand.state != Strand.State.TIMED_WAITING) {
|
||||
Strand.sleep(1)
|
||||
}
|
||||
mainStrand.interrupt()
|
||||
}
|
||||
|
||||
val testClock = TestClock(stoppedClock)
|
||||
val advancedClock = Clock.offset(stoppedClock, Duration.ofHours(10))
|
||||
|
||||
try {
|
||||
testClock.awaitWithDeadline(advancedClock.instant(), SettableFuture.create<Boolean>())
|
||||
fail("Expected InterruptedException")
|
||||
} catch (exception: InterruptedException) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If this test seems to hang and throw an NPE, then likely that quasar suspendables scanner has not been
|
||||
* run on core module (in IntelliJ, open gradle side tab and run:
|
||||
|
Loading…
x
Reference in New Issue
Block a user