mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-23 05:07:27 +00:00
fix cvar not being notified when Arc<Shared<DB>> is dropped
This commit is contained in:
parent
252d21e358
commit
2fc0a3c08f
1 changed files with 26 additions and 13 deletions
|
@ -22,7 +22,7 @@ pub struct Storage<DB: HasJars> {
|
||||||
///
|
///
|
||||||
/// Even though this struct is stored in an `Arc`, we sometimes get mutable access to it
|
/// Even though this struct is stored in an `Arc`, we sometimes get mutable access to it
|
||||||
/// by using `Arc::get_mut`. This is only possible when all parallel snapshots have been dropped.
|
/// by using `Arc::get_mut`. This is only possible when all parallel snapshots have been dropped.
|
||||||
shared: Arc<Shared<DB>>,
|
shared: Shared<DB>,
|
||||||
|
|
||||||
/// The "ingredients" structure stores the information about how to find each ingredient in the database.
|
/// The "ingredients" structure stores the information about how to find each ingredient in the database.
|
||||||
/// It allows us to take the [`IngredientIndex`] assigned to a particular ingredient
|
/// It allows us to take the [`IngredientIndex`] assigned to a particular ingredient
|
||||||
|
@ -43,11 +43,11 @@ struct Shared<DB: HasJars> {
|
||||||
/// Contains the data for each jar in the database.
|
/// Contains the data for each jar in the database.
|
||||||
/// Each jar stores its own structs in there that ultimately contain ingredients
|
/// Each jar stores its own structs in there that ultimately contain ingredients
|
||||||
/// (types that implement the [`Ingredient`] trait, like [`crate::function::FunctionIngredient`]).
|
/// (types that implement the [`Ingredient`] trait, like [`crate::function::FunctionIngredient`]).
|
||||||
jars: DB::Jars,
|
jars: Option<Arc<DB::Jars>>,
|
||||||
|
|
||||||
/// Conditional variable that is used to coordinate cancellation.
|
/// Conditional variable that is used to coordinate cancellation.
|
||||||
/// When the main thread writes to the database, it blocks until each of the snapshots can be cancelled.
|
/// When the main thread writes to the database, it blocks until each of the snapshots can be cancelled.
|
||||||
cvar: Condvar,
|
cvar: Arc<Condvar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// ANCHOR: default
|
// ANCHOR: default
|
||||||
|
@ -59,10 +59,10 @@ where
|
||||||
let mut routes = Routes::new();
|
let mut routes = Routes::new();
|
||||||
let jars = DB::create_jars(&mut routes);
|
let jars = DB::create_jars(&mut routes);
|
||||||
Self {
|
Self {
|
||||||
shared: Arc::new(Shared {
|
shared: Shared {
|
||||||
jars,
|
jars: Some(Arc::new(jars)),
|
||||||
cvar: Default::default(),
|
cvar: Arc::new(Default::default()),
|
||||||
}),
|
},
|
||||||
routes: Arc::new(routes),
|
routes: Arc::new(routes),
|
||||||
runtime: Runtime::default(),
|
runtime: Runtime::default(),
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,7 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn jars(&self) -> (&DB::Jars, &Runtime) {
|
pub fn jars(&self) -> (&DB::Jars, &Runtime) {
|
||||||
(&self.shared.jars, &self.runtime)
|
(self.shared.jars.as_ref().unwrap(), &self.runtime)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn runtime(&self) -> &Runtime {
|
pub fn runtime(&self) -> &Runtime {
|
||||||
|
@ -111,17 +111,17 @@ where
|
||||||
|
|
||||||
// Acquire `&mut` access to `self.shared` -- this is only possible because
|
// Acquire `&mut` access to `self.shared` -- this is only possible because
|
||||||
// the snapshots have all been dropped, so we hold the only handle to the `Arc`.
|
// the snapshots have all been dropped, so we hold the only handle to the `Arc`.
|
||||||
let shared = Arc::get_mut(&mut self.shared).unwrap();
|
let jars = Arc::get_mut(self.shared.jars.as_mut().unwrap()).unwrap();
|
||||||
|
|
||||||
// Inform other ingredients that a new revision has begun.
|
// Inform other ingredients that a new revision has begun.
|
||||||
// This gives them a chance to free resources that were being held until the next revision.
|
// This gives them a chance to free resources that were being held until the next revision.
|
||||||
let routes = self.routes.clone();
|
let routes = self.routes.clone();
|
||||||
for route in routes.reset_routes() {
|
for route in routes.reset_routes() {
|
||||||
route(&mut shared.jars).reset_for_new_revision();
|
route(jars).reset_for_new_revision();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return mut ref to jars + runtime.
|
// Return mut ref to jars + runtime.
|
||||||
(&mut shared.jars, &mut self.runtime)
|
(jars, &mut self.runtime)
|
||||||
}
|
}
|
||||||
// ANCHOR_END: jars_mut
|
// ANCHOR_END: jars_mut
|
||||||
|
|
||||||
|
@ -136,7 +136,7 @@ where
|
||||||
self.runtime.set_cancellation_flag();
|
self.runtime.set_cancellation_flag();
|
||||||
|
|
||||||
// If we have unique access to the jars, we are done.
|
// If we have unique access to the jars, we are done.
|
||||||
if Arc::get_mut(&mut self.shared).is_some() {
|
if Arc::get_mut(self.shared.jars.as_mut().unwrap()).is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +155,19 @@ where
|
||||||
|
|
||||||
pub fn ingredient(&self, ingredient_index: IngredientIndex) -> &dyn Ingredient<DB> {
|
pub fn ingredient(&self, ingredient_index: IngredientIndex) -> &dyn Ingredient<DB> {
|
||||||
let route = self.routes.route(ingredient_index);
|
let route = self.routes.route(ingredient_index);
|
||||||
route(&self.shared.jars)
|
route(self.shared.jars.as_ref().unwrap())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<DB> Clone for Shared<DB>
|
||||||
|
where
|
||||||
|
DB: HasJars,
|
||||||
|
{
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
Self {
|
||||||
|
jars: self.jars.clone(),
|
||||||
|
cvar: self.cvar.clone(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -164,6 +176,7 @@ where
|
||||||
DB: HasJars,
|
DB: HasJars,
|
||||||
{
|
{
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
|
drop(self.jars.take());
|
||||||
self.cvar.notify_all();
|
self.cvar.notify_all();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue