summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorBen Blum <bblum@andrew.cmu.edu>2013-07-02 13:13:07 -0400
committerBen Blum <bblum@andrew.cmu.edu>2013-07-20 05:08:55 -0400
commit55adc4467b4364d949774d5bfd1eba4a16c0b810 (patch)
tree7a029b032369c84298df542fda48108aab7dd972 /src/libstd
parent28c9ba91d85e651ecf3568159bc3dfb45882baf8 (diff)
downloadrust-55adc4467b4364d949774d5bfd1eba4a16c0b810.tar.gz
rust-55adc4467b4364d949774d5bfd1eba4a16c0b810.zip
Add AtomicOption::fill() and AtomicOption::is_empty()
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/unstable/atomics.rs38
1 files changed, 38 insertions, 0 deletions
diff --git a/src/libstd/unstable/atomics.rs b/src/libstd/unstable/atomics.rs
index 1e5ac305df3..dbb9c83ea39 100644
--- a/src/libstd/unstable/atomics.rs
+++ b/src/libstd/unstable/atomics.rs
@@ -272,6 +272,30 @@ impl<T> AtomicOption<T> {
             self.swap(cast::transmute(0), order)
         }
     }
+
+    /// A compare-and-swap. Succeeds if the option is 'None' and returns 'None'
+    /// if so. If the option was already 'Some', returns 'Some' of the rejected
+    /// value.
+    #[inline]
+    pub fn fill(&mut self, val: ~T, order: Ordering) -> Option<~T> {
+        unsafe {
+            let val = cast::transmute(val);
+            let expected = cast::transmute(0);
+            let oldval = atomic_compare_and_swap(&mut self.p, expected, val, order);
+            if oldval == expected {
+                None
+            } else {
+                Some(cast::transmute(val))
+            }
+        }
+    }
+
+    /// Be careful: The caller must have some external method of ensuring the
+    /// result does not get invalidated by another task after this returns.
+    #[inline]
+    pub fn is_empty(&mut self, order: Ordering) -> bool {
+        unsafe { atomic_load(&self.p, order) == cast::transmute(0) }
+    }
 }
 
 #[unsafe_destructor]
@@ -375,6 +399,11 @@ mod test {
     }
 
     #[test]
+    fn option_empty() {
+        assert!(AtomicOption::empty::<()>().is_empty(SeqCst));
+    }
+
+    #[test]
     fn option_swap() {
         let mut p = AtomicOption::new(~1);
         let a = ~2;
@@ -398,4 +427,13 @@ mod test {
         assert_eq!(p.take(SeqCst), Some(~2));
     }
 
+    #[test]
+    fn option_fill() {
+        let mut p = AtomicOption::new(~1);
+        assert!(p.fill(~2, SeqCst).is_some()); // should fail; shouldn't leak!
+        assert_eq!(p.take(SeqCst), Some(~1));
+
+        assert!(p.fill(~2, SeqCst).is_none()); // shouldn't fail
+        assert_eq!(p.take(SeqCst), Some(~2));
+    }
 }