Skip to content

Instantly share code, notes, and snippets.

@morj
Created May 16, 2023 15:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save morj/0f1d48b9f0974fda11d6d4d9a8965c6b to your computer and use it in GitHub Desktop.
Save morj/0f1d48b9f0974fda11d6d4d9a8965c6b to your computer and use it in GitHub Desktop.
@file:Suppress("UNCHECKED_CAST")
package circlet.platform.server.application
import java.util.concurrent.atomic.*
class BusyWaitSingleton<T>(private val factory: () -> T) {
private val value = AtomicReference<State>(State.Empty)
fun singleton(): T {
while (true) {
when (val state = value.get()) {
State.Empty -> {
if (value.compareAndSet(State.Empty, State.Initializing)) {
val result = factory()
if (!value.compareAndSet(State.Initializing, State.Initialized(result))) {
error("Invalid state")
}
return result
}
}
is State.Initialized<*> -> return state.value as T
State.Initializing -> Unit // continue loop: busy wait
}
}
}
private sealed class State {
class Initialized<T>(val value: T) : State()
object Initializing : State()
object Empty : State()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment