Starting to mess with promises
Going to want async IO, I think. And it's a fun detail that I guess I'm in charge of deciding when to run promise completion functions. :D
This commit is contained in:
parent
c1d86676c3
commit
5be0ffa08f
7 changed files with 251 additions and 74 deletions
|
|
@ -1,9 +1,11 @@
|
|||
use oden_js::{
|
||||
module::loader::{ModuleLoader, ModuleSource},
|
||||
Context, ContextRef, Result, Runtime, Value,
|
||||
Context, ContextRef, Promise, Result, Runtime, Value, ValueResult,
|
||||
};
|
||||
use std::collections::HashMap;
|
||||
use std::ffi::OsStr;
|
||||
use std::path::Path;
|
||||
use std::sync::atomic::{AtomicU64, Ordering};
|
||||
use std::sync::mpsc::{channel, Receiver};
|
||||
|
||||
pub mod graphics;
|
||||
|
|
@ -37,6 +39,21 @@ impl ModuleLoader for Loader {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Eq, PartialEq, Hash, Debug, Clone, Copy)]
|
||||
pub struct PromiseHandle(u64);
|
||||
|
||||
impl PromiseHandle {
|
||||
pub fn new() -> Self {
|
||||
static NEXT_ID: AtomicU64 = AtomicU64::new(0);
|
||||
PromiseHandle(NEXT_ID.fetch_add(1, Ordering::SeqCst))
|
||||
}
|
||||
}
|
||||
|
||||
pub enum ScriptEvent {
|
||||
AddPromise(PromiseHandle, Promise),
|
||||
CompletePromise(PromiseHandle, Box<dyn FnOnce(&ContextRef) -> ValueResult>),
|
||||
}
|
||||
|
||||
pub struct ScriptContext {
|
||||
context: Context,
|
||||
init: Value,
|
||||
|
|
@ -46,6 +63,9 @@ pub struct ScriptContext {
|
|||
gfx: graphics::GraphicsAPI,
|
||||
_assets: assets::AssetsAPI,
|
||||
gfx_receive: Receiver<graphics::GraphicsCommand>,
|
||||
|
||||
script_receive: Receiver<ScriptEvent>,
|
||||
promises: HashMap<PromiseHandle, Promise>,
|
||||
}
|
||||
|
||||
impl ScriptContext {
|
||||
|
|
@ -58,6 +78,7 @@ impl ScriptContext {
|
|||
context.add_intrinsic_operators();
|
||||
|
||||
let (gfx_send, gfx_receive) = channel();
|
||||
let (script_send, script_receive) = channel();
|
||||
|
||||
let gfx = graphics::GraphicsAPI::define(&context, gfx_send.clone())
|
||||
.expect("Graphics module should load without error");
|
||||
|
|
@ -89,6 +110,9 @@ impl ScriptContext {
|
|||
gfx_receive,
|
||||
|
||||
_assets: assets,
|
||||
|
||||
script_receive,
|
||||
promises: HashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -96,18 +120,52 @@ impl ScriptContext {
|
|||
// We would want a bi-directional gate for frames to not let the
|
||||
// game thread go to fast probably? And to discard whole frames &c.
|
||||
|
||||
pub fn init(&self) {
|
||||
self.init.call(&self.context).expect("Exception in init");
|
||||
pub fn init(&mut self) {
|
||||
self.init
|
||||
.call(&self.context, &[])
|
||||
.expect("Exception in init");
|
||||
}
|
||||
|
||||
pub fn update(&self) {
|
||||
pub fn update(&mut self) {
|
||||
// Handle any promises that have completed before calling update.
|
||||
while let Ok(event) = self.script_receive.try_recv() {
|
||||
match event {
|
||||
// TODO: Capture debugging information.
|
||||
ScriptEvent::AddPromise(handle, promise) => {
|
||||
self.promises.insert(handle, promise);
|
||||
}
|
||||
ScriptEvent::CompletePromise(handle, value_producer) => {
|
||||
if let Some(promise) = self.promises.remove(&handle) {
|
||||
let result = value_producer(&self.context);
|
||||
match result {
|
||||
Ok(v) => {
|
||||
promise.resolve(&self.context, &v);
|
||||
}
|
||||
Err(e) => {
|
||||
let error = e.to_js_error(&self.context);
|
||||
promise.reject(&self.context, &error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Tell the runtime to process all pending "jobs".
|
||||
self.context
|
||||
.process_all_jobs()
|
||||
.expect("Error processing async jobs");
|
||||
|
||||
// Now run the update function.
|
||||
self.update
|
||||
.call(&self.context)
|
||||
.call(&self.context, &[])
|
||||
.expect("Exception in update");
|
||||
}
|
||||
|
||||
pub fn render(&self) -> Vec<graphics::GraphicsCommand> {
|
||||
self.draw.call(&self.context).expect("Exception in draw");
|
||||
pub fn render(&mut self) -> Vec<graphics::GraphicsCommand> {
|
||||
self.draw
|
||||
.call(&self.context, &[])
|
||||
.expect("Exception in draw");
|
||||
self.gfx.end_frame();
|
||||
|
||||
let mut commands = Vec::new();
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue