about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAriel Ben-Yehuda <arielb1@mail.tau.ac.il>2015-07-20 15:48:24 +0300
committerAriel Ben-Yehuda <ariel.byd@gmail.com>2015-08-06 14:16:52 +0300
commit03ee3f5c204cb9b20c58a5cd2d61dc792727dad7 (patch)
tree35456b07c4c96009ea260208613d8df70eb15a9f
parent859d2954ed974e4d81ea4c20140f6f15f4c6077e (diff)
downloadrust-03ee3f5c204cb9b20c58a5cd2d61dc792727dad7.tar.gz
rust-03ee3f5c204cb9b20c58a5cd2d61dc792727dad7.zip
add an Ivar for write-only variables
-rw-r--r--src/librustc_data_structures/ivar.rs70
-rw-r--r--src/librustc_data_structures/lib.rs1
2 files changed, 71 insertions, 0 deletions
diff --git a/src/librustc_data_structures/ivar.rs b/src/librustc_data_structures/ivar.rs
new file mode 100644
index 00000000000..c16a2ea077c
--- /dev/null
+++ b/src/librustc_data_structures/ivar.rs
@@ -0,0 +1,70 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+use std::cell::Cell;
+
+/// A write-once variable. When constructed, it is empty, and
+/// can only be set once.
+///
+/// Ivars ensure that data that can only be initialised once. A full
+/// implementation is used for concurrency and blocks on a read of an
+/// unfulfilled value. This implementation is more minimal and panics
+/// if you attempt to read the value before it has been set. It is also
+/// not `Sync`, but may be extended in the future to be usable as a true
+/// concurrency type.
+#[derive(PartialEq)]
+pub struct Ivar<T: Copy> {
+    data: Cell<Option<T>>
+}
+
+impl<T: Copy> Ivar<T> {
+    pub fn new() -> Ivar<T> {
+        Ivar {
+            data: Cell::new(None)
+        }
+    }
+
+    pub fn get(&self) -> Option<T> {
+        self.data.get()
+    }
+
+    pub fn fulfill(&self, value: T) {
+        assert!(self.data.get().is_none(),
+                "Value already set!");
+        self.data.set(Some(value));
+    }
+
+    pub fn is_fulfilled(&self) -> bool {
+        self.data.get().is_some()
+    }
+
+    pub fn unwrap(&self) -> T {
+        self.get().unwrap()
+    }
+}
+
+impl<T: Copy+fmt::Debug> fmt::Debug for Ivar<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.get() {
+            Some(val) => write!(f, "Ivar({:?})", val),
+            None => f.write_str("Ivar(<unfulfilled>)")
+        }
+    }
+}
+
+impl<T: Copy> Clone for Ivar<T> {
+    fn clone(&self) -> Ivar<T> {
+        match self.get() {
+            Some(val) => Ivar { data: Cell::new(Some(val)) },
+            None => Ivar::new()
+        }
+    }
+}
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 1f8f7694ff9..558d15610df 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -36,4 +36,5 @@ extern crate serialize as rustc_serialize; // used by deriving
 pub mod snapshot_vec;
 pub mod graph;
 pub mod bitvec;
+pub mod ivar;
 pub mod unify;