///|
fn DialogCompletionStore::DialogCompletionStore() -> DialogCompletionStore {
{ pending: [], }
}
///|
fn DialogCompletionStore::register(
self : DialogCompletionStore,
dialog : Int64,
) -> PendingDialogCompletion {
let completion = PendingDialogCompletion::{
dialog,
state: Waiting,
changed: @async.CondVar::Cond(),
}
self.pending.push(completion)
completion
}
///|
fn DialogCompletionStore::remove(
self : DialogCompletionStore,
dialog : Int64,
) -> Unit {
for index, completion in self.pending {
if completion.dialog == dialog {
ignore(self.pending.remove(index))
return
}
}
}
///|
fn DialogCompletionStore::route_completion(
self : DialogCompletionStore,
completion : @native.NativeDialogCompletion?,
) -> Bool {
guard completion is Some(completion) else { return false }
for pending in self.pending {
if pending.dialog == completion.dialog {
if pending.state is Waiting {
pending.state = Completed(completion.result)
pending.changed.broadcast()
}
return true
}
}
true
}
///|
async fn DialogCompletionStore::wait(
self : DialogCompletionStore,
dialog : Int64,
) -> String {
let completion = self.register(dialog)
defer self.remove(dialog)
while completion.state is Waiting {
completion.changed.wait()
}
match completion.state {
Completed(Ok(result)) => result
Completed(Err(error)) => raise error
Waiting => abort("dialog completion resumed without a result")
}
}
///|
async fn wait_for_failure_dialog(
events : RuntimeEventPump,
wakeup : RuntimeWakeup,
dialog : Int64,
) -> Unit raise AppRunError {
let completion = events.dialog_completions.register(dialog)
defer events.dialog_completions.remove(dialog)
drive_wakeup_until(wakeup, () => !(completion.state is Waiting), () => {
events.poll_native_events()
})
match completion.state {
Completed(Ok(_)) => ()
Completed(Err(error)) =>
raise native_run_error("complete failure dialog", error)
Waiting => abort("dialog completion resumed without a result")
}
}