diff --git a/lib/src/evolution.rs b/lib/src/evolution.rs index 8ebc28aeb..c9122dd55 100644 --- a/lib/src/evolution.rs +++ b/lib/src/evolution.rs @@ -13,7 +13,7 @@ // limitations under the License. use std::collections::{HashMap, HashSet}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use crate::commit::Commit; use crate::commit_builder::CommitBuilder; @@ -316,7 +316,7 @@ impl State { } pub enum EvolutionRef<'a, 'm: 'a, 'r: 'm> { - Readonly(&'a ReadonlyEvolution<'r>), + Readonly(Arc), Mutable(&'a MutableEvolution<'m, 'r>), } @@ -364,17 +364,16 @@ impl EvolutionRef<'_, '_, '_> { /// change id as A). Then C is rebased to somewhere else and becomes C'. /// We will choose that C' as effective successor even though it has a /// different change id and is not a descendant of one that does. - pub fn new_parent(&self, old_parent_id: &CommitId) -> HashSet { + pub fn new_parent(&self, store: &StoreWrapper, old_parent_id: &CommitId) -> HashSet { match self { - EvolutionRef::Readonly(evolution) => evolution.new_parent(old_parent_id), + EvolutionRef::Readonly(evolution) => evolution.new_parent(store, old_parent_id), EvolutionRef::Mutable(evolution) => evolution.new_parent(old_parent_id), } } } -pub struct ReadonlyEvolution<'r> { - repo: &'r ReadonlyRepo, - state: Mutex>>, +pub struct ReadonlyEvolution { + state: State, } pub trait EvolveListener { @@ -394,48 +393,41 @@ pub trait EvolveListener { ); } -impl<'r> ReadonlyEvolution<'r> { - pub fn new(repo: &'r ReadonlyRepo) -> Self { +impl ReadonlyEvolution { + pub fn new(repo: &ReadonlyRepo) -> ReadonlyEvolution { ReadonlyEvolution { - repo, - state: Mutex::new(None), + state: State::calculate(repo.as_repo_ref()), } } - fn get_state(&self) -> Arc { - let mut locked_state = self.state.lock().unwrap(); - if locked_state.is_none() { - locked_state.replace(Arc::new(State::calculate(self.repo.as_repo_ref()))); - } - locked_state.as_ref().unwrap().clone() - } - - pub fn start_modification<'m>(&self, repo: &'m MutableRepo<'r>) -> MutableEvolution<'r, 'm> { + pub fn start_modification<'r: 'm, 'm>( + &self, + repo: &'m MutableRepo<'r>, + ) -> MutableEvolution<'r, 'm> { MutableEvolution { repo, - state: self.get_state().as_ref().clone(), + state: self.state.clone(), } } pub fn successors(&self, commit_id: &CommitId) -> HashSet { - self.get_state().successors(commit_id) + self.state.successors(commit_id) } pub fn is_obsolete(&self, commit_id: &CommitId) -> bool { - self.get_state().is_obsolete(commit_id) + self.state.is_obsolete(commit_id) } pub fn is_orphan(&self, commit_id: &CommitId) -> bool { - self.get_state().is_orphan(commit_id) + self.state.is_orphan(commit_id) } pub fn is_divergent(&self, change_id: &ChangeId) -> bool { - self.get_state().is_divergent(change_id) + self.state.is_divergent(change_id) } - pub fn new_parent(&self, old_parent_id: &CommitId) -> HashSet { - self.get_state() - .new_parent(self.repo.store(), old_parent_id) + pub fn new_parent(&self, store: &StoreWrapper, old_parent_id: &CommitId) -> HashSet { + self.state.new_parent(store, old_parent_id) } } diff --git a/lib/src/repo.rs b/lib/src/repo.rs index bd539298f..201087bca 100644 --- a/lib/src/repo.rs +++ b/lib/src/repo.rs @@ -117,7 +117,7 @@ pub struct ReadonlyRepo { index: Mutex>>, working_copy: Arc>, view: ReadonlyView, - evolution: Option>, + evolution: Mutex>>, } impl Debug for ReadonlyRepo { @@ -235,14 +235,9 @@ impl ReadonlyRepo { index: Mutex::new(None), working_copy: Arc::new(Mutex::new(working_copy)), view, - evolution: None, + evolution: Mutex::new(None), }; - let mut repo = Arc::new(repo); - let repo_ref: &ReadonlyRepo = repo.as_ref(); - let static_lifetime_repo: &'static ReadonlyRepo = unsafe { std::mem::transmute(repo_ref) }; - - let evolution = ReadonlyEvolution::new(static_lifetime_repo); - Arc::get_mut(&mut repo).unwrap().evolution = Some(evolution); + let repo = Arc::new(repo); repo.working_copy_locked() .check_out(checkout_commit) @@ -294,10 +289,12 @@ impl ReadonlyRepo { &self.view } - pub fn evolution<'a>(&'a self) -> &ReadonlyEvolution<'a> { - let evolution: &ReadonlyEvolution<'static> = self.evolution.as_ref().unwrap(); - let evolution: &ReadonlyEvolution<'a> = unsafe { std::mem::transmute(evolution) }; - evolution + pub fn evolution(&self) -> Arc { + let mut locked_evolution = self.evolution.lock().unwrap(); + if locked_evolution.is_none() { + locked_evolution.replace(Arc::new(ReadonlyEvolution::new(self))); + } + locked_evolution.as_ref().unwrap().clone() } pub fn index(&self) -> Arc { @@ -349,12 +346,7 @@ impl ReadonlyRepo { } pub fn start_transaction(&self, description: &str) -> Transaction { - let mut_repo = MutableRepo::new( - self, - self.index(), - &self.view, - &self.evolution.as_ref().unwrap(), - ); + let mut_repo = MutableRepo::new(self, self.index(), &self.view, self.evolution()); Transaction::new(mut_repo, description) } @@ -366,25 +358,15 @@ impl ReadonlyRepo { .unwrap(); self.op_id = operation.id().clone(); self.view = ReadonlyView::new(self.store.clone(), operation.view().take_store_view()); - let repo_ref: &ReadonlyRepo = self; - let static_lifetime_repo: &'static ReadonlyRepo = unsafe { std::mem::transmute(repo_ref) }; - { - let mut locked_index = self.index.lock().unwrap(); - locked_index.take(); - } - self.evolution = Some(ReadonlyEvolution::new(static_lifetime_repo)); + self.index.lock().unwrap().take(); + self.evolution.lock().unwrap().take(); } pub fn reload_at(&mut self, operation: &Operation) { self.op_id = operation.id().clone(); self.view = ReadonlyView::new(self.store.clone(), operation.view().take_store_view()); - let repo_ref: &ReadonlyRepo = self; - let static_lifetime_repo: &'static ReadonlyRepo = unsafe { std::mem::transmute(repo_ref) }; - { - let mut locked_index = self.index.lock().unwrap(); - locked_index.take(); - } - self.evolution = Some(ReadonlyEvolution::new(static_lifetime_repo)); + self.index.lock().unwrap().take(); + self.evolution.lock().unwrap().take(); } } @@ -490,14 +472,9 @@ impl RepoLoader { index: Mutex::new(None), working_copy: Arc::new(Mutex::new(working_copy)), view, - evolution: None, + evolution: Mutex::new(None), }; - let mut repo = Arc::new(repo); - let repo_ref: &ReadonlyRepo = repo.as_ref(); - let static_lifetime_repo: &'static ReadonlyRepo = unsafe { std::mem::transmute(repo_ref) }; - let evolution = ReadonlyEvolution::new(static_lifetime_repo); - Arc::get_mut(&mut repo).unwrap().evolution = Some(evolution); - Ok(repo) + Ok(Arc::new(repo)) } } @@ -513,7 +490,7 @@ impl<'r> MutableRepo<'r> { repo: &'r ReadonlyRepo, index: Arc, view: &ReadonlyView, - evolution: &ReadonlyEvolution<'r>, + evolution: Arc, ) -> Arc> { let mut_view = view.start_modification(); let mut_index = MutableIndex::incremental(index);