From 8ebf1a2f28ced8c23ad03f6a98b84711cf59c6b2 Mon Sep 17 00:00:00 2001 From: Erin Date: Mon, 18 Sep 2017 22:30:27 -0500 Subject: [PATCH] +lib/once: a little library to make sure stuff only gets called once --- lib/once/Cargo.lock | 4 ++++ lib/once/Cargo.toml | 6 ++++++ lib/once/src/lib.rs | 45 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 lib/once/Cargo.lock create mode 100644 lib/once/Cargo.toml create mode 100644 lib/once/src/lib.rs 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(); +}