Skip to content

Instantly share code, notes, and snippets.

@zicklag
Last active November 8, 2023 16:42
Show Gist options
  • Save zicklag/de14ce29d7c6977999286efe949f77ef to your computer and use it in GitHub Desktop.
Save zicklag/de14ce29d7c6977999286efe949f77ef to your computer and use it in GitHub Desktop.
Piccolo Singleton Manager
pub struct LuaSingletons {
singletons: Rc<AtomicCell<HashMap<usize, Box<dyn Any>>>>,
}
impl Default for LuaSingletons {
fn default() -> Self {
Self {
singletons: Rc::new(AtomicCell::new(HashMap::default())),
}
}
}
impl LuaSingletons {
/// Fetch a lua singleton, initializing it if it has not yet been created.
///
/// The singleton is defined by a function pointer that returns a stashable value.
fn get<
'gc,
S: Fetchable<'gc, Fetched = T> + 'static,
T: Stashable<'gc, Stashed = S> + Clone + Copy + 'gc,
>(
&self,
ctx: Context<'gc>,
singleton: fn(Context<'gc>) -> T,
) -> T {
let map = self.singletons.borrow_mut();
let id = singleton as usize;
if let Some(entry) = map.get(&id) {
let stashed = entry.downcast_ref::<S>().expect(
"Encountered two functions with different return types and \
the same function pointer.",
);
ctx.state.registry.fetch(stashed)
} else {
drop(map); // Make sure we don't deadlock
let v = singleton(ctx);
let stashed = ctx.state.registry.stash(&ctx, v);
self.singletons.borrow_mut().insert(id, Box::new(stashed));
v
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment