]> git.proxmox.com Git - cargo.git/commitdiff
Use LazyCell to implement lazy Config
authorAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 20 Jul 2016 23:47:14 +0000 (02:47 +0300)
committerAleksey Kladov <aleksey.kladov@gmail.com>
Wed, 20 Jul 2016 23:47:14 +0000 (02:47 +0300)
src/cargo/core/package.rs
src/cargo/util/config.rs
src/cargo/util/lazy_cell.rs

index c08fa0723cb7f0c6cf4f842b18de8ad9d5d070c8..112d68b0653ce6da0628ea75143b830fc69fb297 100644 (file)
@@ -131,7 +131,7 @@ impl<'cfg> PackageSet<'cfg> {
                sources: SourceMap<'cfg>) -> PackageSet<'cfg> {
         PackageSet {
             packages: package_ids.iter().map(|id| {
-                (id.clone(), LazyCell::new(None))
+                (id.clone(), LazyCell::new())
             }).collect(),
             sources: RefCell::new(sources),
         }
index 2c7d1befb41efda8b66ab1b39c551ece98b640c3..16298a43ac5bf70ea38d7cb43b483c14f67be4da 100644 (file)
@@ -1,4 +1,4 @@
-use std::cell::{RefCell, RefMut, Ref, Cell};
+use std::cell::{RefCell, RefMut, Cell};
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::collections::hash_map::{HashMap};
 use std::env;
@@ -15,7 +15,7 @@ use toml;
 use core::shell::{Verbosity, ColorConfig};
 use core::{MultiShell, Workspace};
 use util::{CargoResult, CargoError, ChainError, Rustc, internal, human};
-use util::Filesystem;
+use util::{Filesystem, LazyCell};
 
 use util::toml as cargo_toml;
 
@@ -24,11 +24,10 @@ use self::ConfigValue as CV;
 pub struct Config {
     home_path: Filesystem,
     shell: RefCell<MultiShell>,
-    rustc: RefCell<Option<Rustc>>,
-    values: RefCell<HashMap<String, ConfigValue>>,
-    values_loaded: Cell<bool>,
+    rustc: LazyCell<Rustc>,
+    values: LazyCell<HashMap<String, ConfigValue>>,
     cwd: PathBuf,
-    rustdoc: RefCell<Option<PathBuf>>,
+    rustdoc: LazyCell<PathBuf>,
     target_dir: RefCell<Option<Filesystem>>,
     extra_verbose: Cell<bool>,
     frozen: Cell<bool>,
@@ -42,11 +41,10 @@ impl Config {
         let mut cfg = Config {
             home_path: Filesystem::new(homedir),
             shell: RefCell::new(shell),
-            rustc: RefCell::new(None),
+            rustc: LazyCell::new(),
             cwd: cwd,
-            values: RefCell::new(HashMap::new()),
-            values_loaded: Cell::new(false),
-            rustdoc: RefCell::new(None),
+            values: LazyCell::new(),
+            rustdoc: LazyCell::new(),
             target_dir: RefCell::new(None),
             extra_verbose: Cell::new(false),
             frozen: Cell::new(false),
@@ -96,27 +94,16 @@ impl Config {
         self.shell.borrow_mut()
     }
 
-    pub fn rustdoc(&self) -> CargoResult<Ref<Path>> {
-        if self.rustdoc.borrow().is_none() {
-            *self.rustdoc.borrow_mut() = Some(try!(self.get_tool("rustdoc")));
-        }
-        Ok(Ref::map(self.rustdoc.borrow(), |opt| opt.as_ref().map(AsRef::as_ref).unwrap()))
+    pub fn rustdoc(&self) -> CargoResult<&Path> {
+        self.rustdoc.get_or_try_init(|| self.get_tool("rustdoc")).map(AsRef::as_ref)
     }
 
-    pub fn rustc(&self) -> CargoResult<Ref<Rustc>> {
-        if self.rustc.borrow().is_none() {
-            let path = try!(self.get_tool("rustc"));
-            *self.rustc.borrow_mut() = Some(try!(Rustc::new(path)));
-        }
-        Ok(Ref::map(self.rustc.borrow(), |opt| opt.as_ref().unwrap()))
+    pub fn rustc(&self) -> CargoResult<&Rustc> {
+        self.rustc.get_or_try_init(|| Rustc::new(try!(self.get_tool("rustc"))))
     }
 
-    pub fn values(&self) -> CargoResult<Ref<HashMap<String, ConfigValue>>> {
-        if !self.values_loaded.get() {
-            try!(self.load_values());
-            self.values_loaded.set(true);
-        }
-        Ok(self.values.borrow())
+    pub fn values(&self) -> CargoResult<&HashMap<String, ConfigValue>> {
+        self.values.get_or_try_init(|| self.load_values())
     }
 
     pub fn cwd(&self) -> &Path { &self.cwd }
@@ -354,7 +341,7 @@ impl Config {
         !self.frozen.get() && !self.locked.get()
     }
 
-    fn load_values(&self) -> CargoResult<()> {
+    fn load_values(&self) -> CargoResult<HashMap<String, ConfigValue>> {
         let mut cfg = CV::Table(HashMap::new(), PathBuf::from("."));
 
         try!(walk_tree(&self.cwd, |mut file, path| {
@@ -376,11 +363,10 @@ impl Config {
         }).chain_error(|| human("Couldn't load Cargo configuration")));
 
 
-        *self.values.borrow_mut() = match cfg {
-            CV::Table(map, _) => map,
+        match cfg {
+            CV::Table(map, _) => Ok(map),
             _ => unreachable!(),
-        };
-        Ok(())
+        }
     }
 
     fn scrape_target_dir_config(&mut self) -> CargoResult<()> {
index a13eaf31ba04a793ee964a6deb8df80e5fe8ca68..3cdaa641692d546e059984c2d9ec6185028e3b50 100644 (file)
@@ -16,8 +16,8 @@ pub struct LazyCell<T> {
 
 impl<T> LazyCell<T> {
     /// Creates a new empty lazy cell.
-    pub fn new(init: Option<T>) -> LazyCell<T> {
-        LazyCell { inner: UnsafeCell::new(init) }
+    pub fn new() -> LazyCell<T> {
+        LazyCell { inner: UnsafeCell::new(None) }
     }
 
     /// Put a value into this cell.
@@ -52,4 +52,16 @@ impl<T> LazyCell<T> {
             self.inner.into_inner()
         }
     }
+
+    /// Borrows the contents of this lazy cell, initializing it if necessary.
+    pub fn get_or_try_init<Error, F>(&self, init: F) -> Result<&T, Error>
+        where F: FnOnce() -> Result<T, Error>
+    {
+        if self.borrow().is_none() {
+            if let Err(_) = self.fill(try!(init())) {
+                unreachable!();
+            }
+        }
+        Ok(self.borrow().unwrap())
+    }
 }