Last active
January 23, 2022 15:49
-
-
Save vishna/1cfaa059304bd2e9b8fabe0292297ce7 to your computer and use it in GitHub Desktop.
Suspened Variable in Kotlin - works kinda lateinit but if your variable is late, it will make you wait rather than crash
This file contains hidden or 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
class SuspendedVariable<T>(var scope: CoroutineScope? = GlobalScope) { | |
private var actor = scope?.actor<Op<T>> { | |
var value : T? = null | |
val deferrals = mutableListOf<CompletableDeferred<T>>() | |
try { | |
for (message in channel) { | |
when (message) { | |
is Op.Set -> { | |
value = message.value | |
if (value != null) { | |
deferrals.forEach { it.complete(value) } | |
deferrals.clear() | |
} | |
} | |
is Op.Get -> { | |
if (value != null) { | |
message.deferred.complete(value) | |
} else { | |
deferrals += message.deferred | |
} | |
} | |
} | |
} | |
} catch (cancellationException: CancellationException) { | |
deferrals.forEach { | |
it.completeExceptionally(cancellationException) | |
} | |
} | |
deferrals.clear() | |
tearDown() | |
} | |
fun set(value: T) { | |
scope?.launch { | |
actor?.send(Op.Set(value)) | |
} | |
} | |
suspend fun get() : T { | |
val deferredValue = CompletableDeferred<T>() | |
actor?.send(Op.Get(deferredValue)) | |
return deferredValue.await() | |
} | |
private fun tearDown() { | |
actor = null | |
scope = null | |
} | |
private sealed class Op<T> { | |
class Set<T>(val value: T) : Op<T>() | |
class Get<T>(val deferred: CompletableDeferred<T>) : Op<T>() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment