Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
70b5a0d
commit 294c5a3
Showing
19 changed files
with
289 additions
and
164 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
use crate::db::QueryResult; | ||
|
||
/// Gives access to a specific jar in the database. | ||
/// | ||
/// Nope, the terminology isn't borrowed from Java but from Salsa <https://salsa-rs.github.io/salsa/>, | ||
/// which is an analogy to storing the salsa in different jars. | ||
/// | ||
/// The basic idea is that each crate can define its own jar and the jars can be combined to a single | ||
/// database in the top level crate. Each crate also defines its own `Database` trait. The combination of | ||
/// `Database` trait and the jar allows to write queries in isolation without having to know how they get composed at the upper levels. | ||
/// | ||
/// Salsa further defines a `HasIngredient` trait which slices the jar to a specific storage (e.g. a specific cache). | ||
/// We don't need this just jet because we write our queries by hand. We may want a similar trait if we decide | ||
/// to use a macro to generate the queries. | ||
pub trait HasJar<T> { | ||
/// Gives a read-only reference to the jar. | ||
fn jar(&self) -> QueryResult<&T>; | ||
|
||
fn jar_by_pass_cancellation(&self) -> &T; | ||
|
||
/// Gives a mutable reference to the jar. | ||
fn jar_mut(&mut self) -> &mut T; | ||
} | ||
|
||
pub trait HasJars { | ||
type Jars; | ||
|
||
fn jars(&self) -> &QueryResult<Self::Jars>; | ||
|
||
fn jars_unwrap(&self) -> &Self::Jars; | ||
|
||
fn jars_mut(&mut self) -> &mut Self::Jars; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
#[derive(Debug, Clone, Copy)] | ||
pub enum QueryError { | ||
Cancelled, | ||
} | ||
|
||
pub type QueryResult<T> = Result<T, QueryError>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
use crate::cancellation::{CancellationToken, CancellationTokenSource}; | ||
use crate::db::jars::HasJars; | ||
use crate::db::query::{QueryError, QueryResult}; | ||
use crossbeam::sync::WaitGroup; | ||
use std::sync::Arc; | ||
|
||
pub struct JarStorage<T> | ||
where | ||
T: HasJars, | ||
{ | ||
db: T, | ||
} | ||
|
||
#[derive(Clone, Debug)] | ||
pub struct SharedStorage<T> | ||
where | ||
T: HasJars, | ||
{ | ||
// It's important that the wait group is declared after `jars` to ensure that `jars` is dropped first. | ||
// See https://doc.rust-lang.org/reference/destructors.html | ||
jars: Arc<T::Jars>, | ||
|
||
/// Used to count the references to `jars`. Allows implementing [`jars_mut`] without requiring to clone `jars`. | ||
jars_references: WaitGroup, | ||
|
||
cancellation_token_source: CancellationTokenSource, | ||
} | ||
|
||
impl<T> SharedStorage<T> | ||
where | ||
T: HasJars, | ||
{ | ||
pub(super) fn jars(&self) -> QueryResult<&T::Jars> { | ||
self.err_if_cancelled()?; | ||
Ok(&self.jars) | ||
} | ||
|
||
pub(super) fn jars_mut(&mut self) -> &mut T::Jars { | ||
// Cancel all pending queries. | ||
self.cancellation_token_source.cancel(); | ||
|
||
let existing_wait = std::mem::take(&mut self.jars_references); | ||
existing_wait.wait(); | ||
self.cancellation_token_source = CancellationTokenSource::new(); | ||
|
||
// Now all other references to `self.jars` should have been released. We can now safely return a mutable reference | ||
// to the Arc's content. | ||
let jars = | ||
Arc::get_mut(&mut self.jars).expect("All references to jars should have been released"); | ||
|
||
jars | ||
} | ||
|
||
pub(super) fn err_if_cancelled(&self) -> QueryResult<()> { | ||
if self.cancellation_token_source.is_cancelled() { | ||
Err(QueryError::Cancelled) | ||
} else { | ||
Ok(()) | ||
} | ||
} | ||
} |
Oops, something went wrong.