Last active
August 7, 2018 02:10
-
-
Save Groostav/ac3f4090199153b2db94fa2016b20852 to your computer and use it in GitHub Desktop.
orAsync implementation attempt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
private enum class Side { Left, Right } | |
infix fun Deferred<Boolean>.orAsync(right: Deferred<Boolean>) = async<Boolean> { | |
val left: Deferred<Boolean> = this@orAsync | |
//note: I didnt take a context object. | |
//`infix` might not be possible... | |
// 'short circuit' | |
if(left.isCompleted && left.getCompleted()) return@async true | |
if(right.isCompleted && right.getCompleted()) return@async true | |
//we have no choice but to wait for one of them to return | |
val (side, sideTrue) = select<Pair<Side, Boolean>> { | |
left.onAwait { Side.Left to it } | |
right.onAwait { Side.Right to it } | |
} | |
return@async when { | |
//if that value was true, we're done | |
sideTrue -> true | |
//else wait for the other to complete | |
side == Side.Left -> right.await() | |
side == Side.Right -> left.await() | |
else -> TODO() | |
} | |
} | |
@Test fun `when using async or and one of the two operands returns true`() = runBlocking { | |
val left = CompletableDeferred<Boolean>() | |
val right = CompletableDeferred<Boolean>() | |
val result = left orAsync right | |
delay(10) | |
left.complete(true) | |
assertTrue(result.await()) | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
infix fun Deferred<Boolean>.orAsyncLazy(right: suspend () -> Boolean) = async<Boolean> { | |
val left: Deferred<Boolean> = this@orAsyncLazy | |
// 'short circuit' | |
if(left.isCompleted && left.getCompleted()) return@async true | |
val leftValue = left.await() | |
return@async leftValue || right() | |
} | |
@Test fun `when using orAsyncLazy should not start until left completes`() = runBlocking { | |
val left = CompletableDeferred<Boolean>() | |
val right: suspend () -> Nothing = { TODO("blam: you evaluated right eagerly!") } | |
val result = left orAsyncLazy { right() } | |
delay(10) | |
left.complete(true) | |
assertTrue(result.await()) | |
} | |
@Test fun `when using orAsyncLazy should evaluate right when left is false`() = runBlocking { | |
val left = CompletableDeferred<Boolean>() | |
var evaluatedRight: Boolean = false | |
val right: suspend () -> Boolean = right@ { evaluatedRight = true; return@right true } | |
val result = left orAsyncLazy { right() } | |
delay(10) | |
left.complete(false) | |
assertTrue(result.await()) | |
assertTrue(evaluatedRight) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment