mirror of
https://github.com/martinvonz/jj.git
synced 2025-01-18 10:07:28 +00:00
ReadonlyEvolution: make ReadonlyRepo responsible for lazy calculation
This patch changes it so that `ReadonlyEvolution` does not lazily calculate its state and the caller, i.e. `ReadonlyRepo`, is instead responsible for the laziness. That will allow the caller to make decisions based on whether the state has been calculated. Specifically, we don't want to calculate the evolution state in order to update it incrementally if it hasn't already been calculated. It's better to just leave it uncalculated in that case. As a result of moving the laziness out of `ReadonlyEvolution`, we also don't need to the reference to `ReadonlyRepo` anymore, which simplifies things a bunch. The next patch will continue by making the corresponding change to `MutableEvolution`, which will let us simplify even more.
This commit is contained in:
parent
43315bc9d2
commit
61acee52f4
2 changed files with 37 additions and 68 deletions
|
@ -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<ReadonlyEvolution>),
|
||||
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<CommitId> {
|
||||
pub fn new_parent(&self, store: &StoreWrapper, old_parent_id: &CommitId) -> HashSet<CommitId> {
|
||||
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<Option<Arc<State>>>,
|
||||
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<State> {
|
||||
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<CommitId> {
|
||||
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<CommitId> {
|
||||
self.get_state()
|
||||
.new_parent(self.repo.store(), old_parent_id)
|
||||
pub fn new_parent(&self, store: &StoreWrapper, old_parent_id: &CommitId) -> HashSet<CommitId> {
|
||||
self.state.new_parent(store, old_parent_id)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ pub struct ReadonlyRepo {
|
|||
index: Mutex<Option<Arc<ReadonlyIndex>>>,
|
||||
working_copy: Arc<Mutex<WorkingCopy>>,
|
||||
view: ReadonlyView,
|
||||
evolution: Option<ReadonlyEvolution<'static>>,
|
||||
evolution: Mutex<Option<Arc<ReadonlyEvolution>>>,
|
||||
}
|
||||
|
||||
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<ReadonlyEvolution> {
|
||||
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<ReadonlyIndex> {
|
||||
|
@ -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<ReadonlyIndex>,
|
||||
view: &ReadonlyView,
|
||||
evolution: &ReadonlyEvolution<'r>,
|
||||
evolution: Arc<ReadonlyEvolution>,
|
||||
) -> Arc<MutableRepo<'r>> {
|
||||
let mut_view = view.start_modification();
|
||||
let mut_index = MutableIndex::incremental(index);
|
||||
|
|
Loading…
Reference in a new issue