feat: EvalState.weak_ref()
(cherry picked from commit d7a72c82ebfbfbb1b58fa15044b63648b2109260)
This commit is contained in:
parent
e0dead151e
commit
01c9d0b2d3
2 changed files with 57 additions and 2 deletions
|
|
@ -4,14 +4,14 @@ use anyhow::{bail, Result};
|
||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use nix_c_raw as raw;
|
use nix_c_raw as raw;
|
||||||
use nix_store::path::StorePath;
|
use nix_store::path::StorePath;
|
||||||
use nix_store::store::Store;
|
use nix_store::store::{Store, StoreWeak};
|
||||||
use nix_util::context::Context;
|
use nix_util::context::Context;
|
||||||
use nix_util::string_return::{callback_get_result_string, callback_get_result_string_data};
|
use nix_util::string_return::{callback_get_result_string, callback_get_result_string_data};
|
||||||
use nix_util::{check_call, check_call_opt_key, result_string_init};
|
use nix_util::{check_call, check_call_opt_key, result_string_init};
|
||||||
use std::ffi::{c_char, CString};
|
use std::ffi::{c_char, CString};
|
||||||
use std::os::raw::c_uint;
|
use std::os::raw::c_uint;
|
||||||
use std::ptr::{null, null_mut, NonNull};
|
use std::ptr::{null, null_mut, NonNull};
|
||||||
use std::sync::Arc;
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref INIT: Result<()> = {
|
static ref INIT: Result<()> = {
|
||||||
|
|
@ -38,6 +38,26 @@ pub struct RealisedString {
|
||||||
pub paths: Vec<StorePath>,
|
pub paths: Vec<StorePath>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A [Weak] reference to an [EvalState]
|
||||||
|
pub struct EvalStateWeak {
|
||||||
|
inner: Weak<EvalStateRef>,
|
||||||
|
store: StoreWeak,
|
||||||
|
}
|
||||||
|
impl EvalStateWeak {
|
||||||
|
/// Upgrade the weak reference to a proper [EvalState].
|
||||||
|
///
|
||||||
|
/// If no normal reference to the [EvalState] is around anymore elsewhere, this fails by returning `None`.
|
||||||
|
pub fn upgrade(&self) -> Option<EvalState> {
|
||||||
|
self.inner.upgrade().and_then(|eval_state| {
|
||||||
|
self.store.upgrade().map(|store| EvalState {
|
||||||
|
eval_state: eval_state,
|
||||||
|
store: store,
|
||||||
|
context: Context::new(),
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
struct EvalStateRef {
|
struct EvalStateRef {
|
||||||
eval_state: NonNull<raw::EvalState>,
|
eval_state: NonNull<raw::EvalState>,
|
||||||
}
|
}
|
||||||
|
|
@ -106,6 +126,13 @@ impl EvalState {
|
||||||
pub fn store(&self) -> &Store {
|
pub fn store(&self) -> &Store {
|
||||||
&self.store
|
&self.store
|
||||||
}
|
}
|
||||||
|
pub fn weak_ref(&self) -> EvalStateWeak {
|
||||||
|
EvalStateWeak {
|
||||||
|
inner: Arc::downgrade(&self.eval_state),
|
||||||
|
store: self.store.weak_ref(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses and evaluates a Nix expression `expr`.
|
/// Parses and evaluates a Nix expression `expr`.
|
||||||
///
|
///
|
||||||
/// Expressions can contain relative paths such as `./.` that are resolved relative to the given `path`.
|
/// Expressions can contain relative paths such as `./.` that are resolved relative to the given `path`.
|
||||||
|
|
@ -481,6 +508,32 @@ mod tests {
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn weak_ref() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let store = Store::open("auto", HashMap::new()).unwrap();
|
||||||
|
let es = EvalState::new(store, []).unwrap();
|
||||||
|
let weak = es.weak_ref();
|
||||||
|
let _es = weak.upgrade().unwrap();
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn weak_ref_gone() {
|
||||||
|
gc_registering_current_thread(|| {
|
||||||
|
let weak = {
|
||||||
|
let store = Store::open("auto", HashMap::new()).unwrap();
|
||||||
|
let es = EvalState::new(store, []).unwrap();
|
||||||
|
es.weak_ref()
|
||||||
|
};
|
||||||
|
assert!(weak.upgrade().is_none());
|
||||||
|
assert!(weak.store.upgrade().is_none());
|
||||||
|
assert!(weak.inner.upgrade().is_none());
|
||||||
|
})
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn eval_state_lookup_path() {
|
fn eval_state_lookup_path() {
|
||||||
let import_expression = "import <test_file0> + import <test_file1>";
|
let import_expression = "import <test_file0> + import <test_file1>";
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ pub struct StoreWeak {
|
||||||
}
|
}
|
||||||
impl StoreWeak {
|
impl StoreWeak {
|
||||||
/// Upgrade the weak reference to a proper [Store].
|
/// Upgrade the weak reference to a proper [Store].
|
||||||
|
///
|
||||||
|
/// If no normal reference to the [Store] is around anymore elsewhere, this fails by returning `None`.
|
||||||
pub fn upgrade(&self) -> Option<Store> {
|
pub fn upgrade(&self) -> Option<Store> {
|
||||||
self.inner.upgrade().map(|inner| Store {
|
self.inner.upgrade().map(|inner| Store {
|
||||||
inner,
|
inner,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue