diff --git a/lib/once/Cargo.lock b/lib/once/Cargo.lock new file mode 100644 index 0000000..188f91d --- /dev/null +++ b/lib/once/Cargo.lock @@ -0,0 +1,4 @@ +[root] +name = "once" +version = "0.1.0" + diff --git a/lib/once/Cargo.toml b/lib/once/Cargo.toml new file mode 100644 index 0000000..931c5d9 --- /dev/null +++ b/lib/once/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "once" +version = "0.1.0" +authors = ["Erin "] + +[dependencies] diff --git a/lib/once/src/lib.rs b/lib/once/src/lib.rs new file mode 100644 index 0000000..0b81bf0 --- /dev/null +++ b/lib/once/src/lib.rs @@ -0,0 +1,45 @@ +#![no_std] + +#[cfg(test)] +extern crate std; + +#[macro_export] +macro_rules! assert_first_call { + () => { + assert_first_call!("assertion failed: function called more than once"); + }; + + ($($arg:tt)+) => {{ + use ::core::sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering}; + static CALLED: AtomicBool = ATOMIC_BOOL_INIT; + let called = CALLED.swap(true, Ordering::Relaxed); + assert!(called == false, $($arg)+); + }}; +} + +#[test] +fn test_run_once() { + fn once() { + assert_first_call!(); + } + + once(); +} + +#[test] +fn test_run_once_two_funcs() { + fn once1() {assert_first_call!();} + fn once2() {assert_first_call!();} + + once1(); once2(); +} + +#[test] +#[should_panic] +fn test_run_twice() { + fn once() { + assert_first_call!(); + } + + once(); once(); +}