repo: use OnceCell instead of Mutex<Option<_>> to store index

This is perfect use case of OnceCell per the safety comment in index().
This commit is contained in:
Yuya Nishihara 2022-11-06 12:51:48 +09:00
parent 93b7b34871
commit 2681e8f908

View file

@ -18,10 +18,11 @@ use std::fmt::{Debug, Formatter};
use std::io::ErrorKind; use std::io::ErrorKind;
use std::ops::Deref; use std::ops::Deref;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use std::sync::{Arc, Mutex}; use std::sync::Arc;
use std::{fs, io}; use std::{fs, io};
use itertools::Itertools; use itertools::Itertools;
use once_cell::sync::OnceCell;
use thiserror::Error; use thiserror::Error;
use crate::backend::{Backend, BackendError, ChangeId, CommitId}; use crate::backend::{Backend, BackendError, ChangeId, CommitId};
@ -96,7 +97,7 @@ pub struct ReadonlyRepo {
operation: Operation, operation: Operation,
settings: RepoSettings, settings: RepoSettings,
index_store: Arc<IndexStore>, index_store: Arc<IndexStore>,
index: Mutex<Option<Arc<ReadonlyIndex>>>, index: OnceCell<Arc<ReadonlyIndex>>,
view: View, view: View,
} }
@ -152,7 +153,7 @@ impl ReadonlyRepo {
operation: init_op, operation: init_op,
settings: repo_settings, settings: repo_settings,
index_store, index_store,
index: Mutex::new(None), index: OnceCell::new(),
view, view,
})) }))
} }
@ -199,27 +200,15 @@ impl ReadonlyRepo {
} }
pub fn index(&self) -> &Arc<ReadonlyIndex> { pub fn index(&self) -> &Arc<ReadonlyIndex> {
let mut locked_index = self.index.lock().unwrap(); self.index.get_or_init(|| {
if locked_index.is_none() {
locked_index.replace(
self.index_store self.index_store
.get_index_at_op(&self.operation, &self.store), .get_index_at_op(&self.operation, &self.store)
); })
}
let index: &Arc<ReadonlyIndex> = locked_index.as_ref().unwrap();
// Extend lifetime from that of mutex lock to that of self. Safe since we never
// change value once it's been set (except in `reindex()` but that
// requires a mutable reference).
let index: &Arc<ReadonlyIndex> = unsafe { std::mem::transmute(index) };
index
} }
pub fn reindex(&mut self) -> &Arc<ReadonlyIndex> { pub fn reindex(&mut self) -> &Arc<ReadonlyIndex> {
self.index_store.reinit(); self.index_store.reinit();
{ self.index.take();
let mut locked_index = self.index.lock().unwrap();
locked_index.take();
}
self.index() self.index()
} }
@ -436,7 +425,7 @@ impl RepoLoader {
operation, operation,
settings: self.repo_settings.clone(), settings: self.repo_settings.clone(),
index_store: self.index_store.clone(), index_store: self.index_store.clone(),
index: Mutex::new(Some(index)), index: OnceCell::with_value(index),
view, view,
}; };
Arc::new(repo) Arc::new(repo)
@ -451,7 +440,7 @@ impl RepoLoader {
operation, operation,
settings: self.repo_settings.clone(), settings: self.repo_settings.clone(),
index_store: self.index_store.clone(), index_store: self.index_store.clone(),
index: Mutex::new(None), index: OnceCell::new(),
view, view,
}; };
Arc::new(repo) Arc::new(repo)