about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2013-08-08 19:59:08 -0400
committerBen Blum <bblum@andrew.cmu.edu>2013-08-20 13:28:59 -0400
commitdd406365e1a189c4f229e1eba7ba091605e995ef (patch)
treef3b264a9678d74459b3e5fd16ad697a304b9c005 /src/libstd
parent7f268128954fef84dcbcb7c9fe77e2a107e0bf69 (diff)
downloadrust-dd406365e1a189c4f229e1eba7ba091605e995ef.tar.gz
rust-dd406365e1a189c4f229e1eba7ba091605e995ef.zip
Add assert_once_ever macro. Close #7748. (fixme cf #8472)
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/macros.rs36
-rw-r--r--src/libstd/rt/mod.rs1
2 files changed, 37 insertions, 0 deletions
diff --git a/src/libstd/macros.rs b/src/libstd/macros.rs
index 89c7b294512..600d0bb133e 100644
--- a/src/libstd/macros.rs
+++ b/src/libstd/macros.rs
@@ -40,3 +40,39 @@ macro_rules! rtabort(
     } )
 )
 
+macro_rules! assert_once_ever(
+    ($( $msg:expr),+) => ( {
+        // FIXME(#8472) extra function should not be needed to hide unsafe
+        fn assert_once_ever() {
+            unsafe {
+                static mut already_happened: int = 0;
+                // Double-check lock to avoid a swap in the common case.
+                if already_happened != 0 ||
+                    ::unstable::intrinsics::atomic_xchg_relaxed(&mut already_happened, 1) != 0 {
+                        fail!(fmt!("assert_once_ever happened twice: %s", fmt!($($msg),+)));
+                }
+            }
+        }
+        assert_once_ever();
+    } )
+)
+
+#[cfg(test)]
+mod tests {
+    #[test]
+    fn test_assert_once_ever_ok() {
+        assert_once_ever!("help i'm stuck in an");
+        assert_once_ever!("assertion error message");
+    }
+
+    #[test] #[ignore(cfg(windows))] #[should_fail]
+    fn test_assert_once_ever_fail() {
+        use task;
+
+        fn f() { assert_once_ever!("if you're seeing this... good!") }
+
+        // linked & watched, naturally
+        task::spawn(f);
+        task::spawn(f);
+    }
+}
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index db1bfdf1bf5..8b3e65b57ab 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -323,6 +323,7 @@ fn run_(main: ~fn(), use_main_sched: bool) -> int {
     // task tree, shut down the schedulers and set the exit code.
     let handles = Cell::new(handles);
     let on_exit: ~fn(bool) = |exit_success| {
+        assert_once_ever!("last task exiting");
 
         let mut handles = handles.take();
         for handle in handles.mut_iter() {