Skip to content

Instantly share code, notes, and snippets.

@Groostav
Created July 26, 2019 19:45
Show Gist options
  • Save Groostav/c0d6d7625db61045064b45b51a51b6d9 to your computer and use it in GitHub Desktop.
Save Groostav/c0d6d7625db61045064b45b51a51b6d9 to your computer and use it in GitHub Desktop.
first crack at mutable event bus context
class EventContext(key: Key): AbstractCoroutineContextElement(key) {
private val completed = CompletableDeferred<Unit>()
private var events: AtomicReference<ImmutableList<EventWrapper>?> = AtomicReference(immutableListOf())
// in this implementation, polling an empty list "closes" it,
// thus, if you poll a list of 1 element, it becomes a list of 0 elements,
// when thats polled, its atomically closed and subsequent offer calls return false.
fun poll(): EventWrapper? {
var initial: ImmutableList<EventWrapper>?
var final: ImmutableList<EventWrapper>?
var result: EventWrapper?
do {
initial = events.get()
result = initial?.firstOrNull()
final = when {
initial == null -> null
initial.isEmpty() -> null
else -> initial.removeAt(0)
}
}
while( ! events.compareAndSet(initial, final))
if(initial != null && final == null){
// polled an empty queue completing it
completed.complete(Unit)
}
return result
}
fun offer(event: EventWrapper): Boolean {
val result = events.updateAndGet { if(it == null) it else (it + event) }
println("offered event ${event.event}: $result")
return result != null && (event == result.lastOrNull() || event in result)
}
//suspends until this nested event loops is completed
suspend fun await() = completed.await()
// unsafe-poll the state of completion (meant for debugging)
val isCompleted: Boolean get() = completed.isCompleted
//need difference in equality for different event busses
// => do not use object
class Key: CoroutineContext.Key<EventContext>
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment