Skip to content

Instantly share code, notes, and snippets.

@KHN190
Last active April 2, 2021 04:16
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 KHN190/d7918bedd3bc047ee25c4befcf7e30d6 to your computer and use it in GitHub Desktop.
Save KHN190/d7918bedd3bc047ee25c4befcf7e30d6 to your computer and use it in GitHub Desktop.
Create singleton instance in Rust
use std::sync::atomic::{AtomicBool, Ordering};
pub trait Loader {
fn load(&self, name: &str);
}
struct ResourceLoader;
impl Loader for ResourceLoader {
fn load(&self, name: &str) {
println!("load {}", name);
}
}
static mut LOADER: Option<&dyn Loader> = None;
static INITIALIZED: AtomicBool = AtomicBool::new(false);
fn set_loader(loader: &'static dyn Loader) {
set_loader_inner(|| loader)
}
fn set_loader_inner<F>(make_loader: F)
where
F: FnOnce() -> &'static dyn Loader,
{
unsafe {
if std::ptr::read(&INITIALIZED).into_inner()
{
println!("loader already initialized");
}
else {
LOADER = Some(make_loader());
INITIALIZED.store(true, Ordering::Relaxed);
}
}
}
fn init_loader() {
let loader = Box::new(ResourceLoader {});
set_loader(Box::leak(loader));
}
pub fn get_loader() -> &'static dyn Loader {
unsafe {
if !std::ptr::read(&INITIALIZED).into_inner()
{
init_loader();
}
LOADER.unwrap()
}
}
mod loader;
fn main() {
let ld = loader::get_loader();
ld.load("what?");
let rs = loader::get_loader();
rs.load("hei!");
}
@KHN190
Copy link
Author

KHN190 commented Apr 2, 2021

Use singleton so you don't have to pass in a logger / resource loader 10 levels deep from a top level function...

Instead, call anywhere in your code:

loader::get_loader().load("hei");

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment