mirror of
https://github.com/ellmau/adf-obdd.git
synced 2025-12-19 09:29:36 +01:00
Add multithread-safe functionality for the dictionary/ordering
* Streamline a couple of API calls * Expose more structs and methods to the public API * Breaking some API (though nothing which is currently used in the binary)
This commit is contained in:
parent
00674f7c5e
commit
84aa627159
@ -47,16 +47,11 @@ impl Adf {
|
|||||||
pub fn from_parser(parser: &AdfParser) -> Self {
|
pub fn from_parser(parser: &AdfParser) -> Self {
|
||||||
log::info!("[Start] instantiating BDD");
|
log::info!("[Start] instantiating BDD");
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
ordering: VarContainer::from_parser(
|
ordering: parser.var_container(),
|
||||||
parser.namelist_rc_refcell(),
|
|
||||||
parser.dict_rc_refcell(),
|
|
||||||
),
|
|
||||||
bdd: Bdd::new(),
|
bdd: Bdd::new(),
|
||||||
ac: vec![Term(0); parser.namelist_rc_refcell().as_ref().borrow().len()],
|
ac: vec![Term(0); parser.dict_size()],
|
||||||
};
|
};
|
||||||
(0..parser.namelist_rc_refcell().borrow().len())
|
(0..parser.dict_size()).into_iter().for_each(|value| {
|
||||||
.into_iter()
|
|
||||||
.for_each(|value| {
|
|
||||||
log::trace!("adding variable {}", Var(value));
|
log::trace!("adding variable {}", Var(value));
|
||||||
result.bdd.variable(Var(value));
|
result.bdd.variable(Var(value));
|
||||||
});
|
});
|
||||||
@ -87,7 +82,7 @@ impl Adf {
|
|||||||
bio_ac: &[biodivine_lib_bdd::Bdd],
|
bio_ac: &[biodivine_lib_bdd::Bdd],
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
ordering: VarContainer::copy(ordering),
|
ordering: ordering.clone(),
|
||||||
bdd: Bdd::new(),
|
bdd: Bdd::new(),
|
||||||
ac: vec![Term(0); bio_ac.len()],
|
ac: vec![Term(0); bio_ac.len()],
|
||||||
};
|
};
|
||||||
@ -900,11 +895,16 @@ mod test {
|
|||||||
parser.parse()(input).unwrap();
|
parser.parse()(input).unwrap();
|
||||||
|
|
||||||
let adf = Adf::from_parser(&parser);
|
let adf = Adf::from_parser(&parser);
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[0], "a");
|
assert_eq!(adf.ordering.name(Var(0)), Some("a".to_string()));
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[1], "c");
|
assert_eq!(adf.ordering.names().read().unwrap()[0], "a");
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[2], "b");
|
assert_eq!(adf.ordering.name(Var(1)), Some("c".to_string()));
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[3], "e");
|
assert_eq!(adf.ordering.names().read().unwrap()[1], "c");
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[4], "d");
|
assert_eq!(adf.ordering.name(Var(2)), Some("b".to_string()));
|
||||||
|
assert_eq!(adf.ordering.names().read().unwrap()[2], "b");
|
||||||
|
assert_eq!(adf.ordering.name(Var(3)), Some("e".to_string()));
|
||||||
|
assert_eq!(adf.ordering.names().read().unwrap()[3], "e");
|
||||||
|
assert_eq!(adf.ordering.name(Var(4)), Some("d".to_string()));
|
||||||
|
assert_eq!(adf.ordering.names().read().unwrap()[4], "d");
|
||||||
|
|
||||||
assert_eq!(adf.ac, vec![Term(4), Term(2), Term(7), Term(15), Term(12)]);
|
assert_eq!(adf.ac, vec![Term(4), Term(2), Term(7), Term(15), Term(12)]);
|
||||||
|
|
||||||
@ -915,11 +915,11 @@ mod test {
|
|||||||
parser.varsort_alphanum();
|
parser.varsort_alphanum();
|
||||||
|
|
||||||
let adf = Adf::from_parser(&parser);
|
let adf = Adf::from_parser(&parser);
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[0], "a");
|
assert_eq!(adf.ordering.names().read().unwrap()[0], "a");
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[1], "b");
|
assert_eq!(adf.ordering.names().read().unwrap()[1], "b");
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[2], "c");
|
assert_eq!(adf.ordering.names().read().unwrap()[2], "c");
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[3], "d");
|
assert_eq!(adf.ordering.names().read().unwrap()[3], "d");
|
||||||
assert_eq!(adf.ordering.names().as_ref().borrow()[4], "e");
|
assert_eq!(adf.ordering.names().read().unwrap()[4], "e");
|
||||||
|
|
||||||
assert_eq!(adf.ac, vec![Term(3), Term(7), Term(2), Term(11), Term(13)]);
|
assert_eq!(adf.ac, vec![Term(3), Term(7), Term(2), Term(11), Term(13)]);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -40,19 +40,17 @@ impl Adf {
|
|||||||
pub fn from_parser(parser: &AdfParser) -> Self {
|
pub fn from_parser(parser: &AdfParser) -> Self {
|
||||||
log::info!("[Start] instantiating BDD");
|
log::info!("[Start] instantiating BDD");
|
||||||
let mut bdd_var_builder = biodivine_lib_bdd::BddVariableSetBuilder::new();
|
let mut bdd_var_builder = biodivine_lib_bdd::BddVariableSetBuilder::new();
|
||||||
let namelist = parser.namelist_rc_refcell().as_ref().borrow().clone();
|
let namelist = parser
|
||||||
|
.namelist()
|
||||||
|
.read()
|
||||||
|
.expect("ReadLock on namelist failed")
|
||||||
|
.clone();
|
||||||
let slice_vec: Vec<&str> = namelist.iter().map(<_>::as_ref).collect();
|
let slice_vec: Vec<&str> = namelist.iter().map(<_>::as_ref).collect();
|
||||||
bdd_var_builder.make_variables(&slice_vec);
|
bdd_var_builder.make_variables(&slice_vec);
|
||||||
let bdd_variables = bdd_var_builder.build();
|
let bdd_variables = bdd_var_builder.build();
|
||||||
let mut result = Self {
|
let mut result = Self {
|
||||||
ordering: VarContainer::from_parser(
|
ordering: parser.var_container(),
|
||||||
parser.namelist_rc_refcell(),
|
ac: vec![bdd_variables.mk_false(); parser.dict_size()],
|
||||||
parser.dict_rc_refcell(),
|
|
||||||
),
|
|
||||||
ac: vec![
|
|
||||||
bdd_variables.mk_false();
|
|
||||||
parser.namelist_rc_refcell().as_ref().borrow().len()
|
|
||||||
],
|
|
||||||
vars: bdd_variables.variables(),
|
vars: bdd_variables.variables(),
|
||||||
varset: bdd_variables,
|
varset: bdd_variables,
|
||||||
rewrite: None,
|
rewrite: None,
|
||||||
|
|||||||
@ -2,49 +2,63 @@
|
|||||||
|
|
||||||
use super::{Term, Var};
|
use super::{Term, Var};
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{cell::RefCell, collections::HashMap, fmt::Display, rc::Rc};
|
use std::{collections::HashMap, fmt::Display, sync::Arc, sync::RwLock};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug)]
|
/// A container which acts as a dictionary as well as an ordering of variables.
|
||||||
pub(crate) struct VarContainer {
|
/// *names* is a list of variable-names and the sequence of the values is inducing the order of variables.
|
||||||
names: Rc<RefCell<Vec<String>>>,
|
/// *mapping* allows to search for a variable name and to receive the corresponding position in the variable list (`names`).
|
||||||
mapping: Rc<RefCell<HashMap<String, usize>>>,
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct VarContainer {
|
||||||
|
names: Arc<RwLock<Vec<String>>>,
|
||||||
|
mapping: Arc<RwLock<HashMap<String, usize>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for VarContainer {
|
impl Default for VarContainer {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
VarContainer {
|
VarContainer {
|
||||||
names: Rc::new(RefCell::new(Vec::new())),
|
names: Arc::new(RwLock::new(Vec::new())),
|
||||||
mapping: Rc::new(RefCell::new(HashMap::new())),
|
mapping: Arc::new(RwLock::new(HashMap::new())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl VarContainer {
|
impl VarContainer {
|
||||||
pub fn from_parser(
|
pub(crate) fn from_parser(
|
||||||
names: Rc<RefCell<Vec<String>>>,
|
names: Arc<RwLock<Vec<String>>>,
|
||||||
mapping: Rc<RefCell<HashMap<String, usize>>>,
|
mapping: Arc<RwLock<HashMap<String, usize>>>,
|
||||||
) -> VarContainer {
|
) -> VarContainer {
|
||||||
VarContainer { names, mapping }
|
VarContainer { names, mapping }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn copy(from: &Self) -> Self {
|
/// Get the [Var] used by the `Bdd` which corresponds to the given [&str].
|
||||||
VarContainer {
|
/// Returns [None] if no matching value is found.
|
||||||
names: from.names.clone(),
|
|
||||||
mapping: from.mapping.clone(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn variable(&self, name: &str) -> Option<Var> {
|
pub fn variable(&self, name: &str) -> Option<Var> {
|
||||||
self.mapping.borrow().get(name).map(|val| Var(*val))
|
self.mapping
|
||||||
|
.read()
|
||||||
|
.ok()
|
||||||
|
.and_then(|map| map.get(name).map(|val| Var(*val)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the name which corresponds to the given [Var].
|
||||||
|
/// Returns [None] if no matching value is found.
|
||||||
pub fn name(&self, var: Var) -> Option<String> {
|
pub fn name(&self, var: Var) -> Option<String> {
|
||||||
self.names.borrow().get(var.value()).cloned()
|
self.names
|
||||||
|
.read()
|
||||||
|
.ok()
|
||||||
|
.and_then(|name| name.get(var.value()).cloned())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
pub(crate) fn names(&self) -> Arc<RwLock<Vec<String>>> {
|
||||||
pub fn names(&self) -> Rc<RefCell<Vec<String>>> {
|
Arc::clone(&self.names)
|
||||||
Rc::clone(&self.names)
|
}
|
||||||
|
|
||||||
|
pub(crate) fn mappings(&self) -> Arc<RwLock<HashMap<String, usize>>> {
|
||||||
|
Arc::clone(&self.mapping)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a [PrintDictionary] for output purposes.
|
||||||
|
pub fn print_dictionary(&self) -> PrintDictionary {
|
||||||
|
PrintDictionary::new(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// A struct which holds the dictionary to print interpretations and allows to instantiate printable interpretations.
|
/// A struct which holds the dictionary to print interpretations and allows to instantiate printable interpretations.
|
||||||
@ -56,7 +70,7 @@ pub struct PrintDictionary {
|
|||||||
impl PrintDictionary {
|
impl PrintDictionary {
|
||||||
pub(crate) fn new(order: &VarContainer) -> Self {
|
pub(crate) fn new(order: &VarContainer) -> Self {
|
||||||
Self {
|
Self {
|
||||||
ordering: VarContainer::copy(order),
|
ordering: order.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/// creates a [PrintableInterpretation] for output purposes
|
/// creates a [PrintableInterpretation] for output purposes
|
||||||
|
|||||||
@ -169,14 +169,16 @@ The enum [`Heuristic`][crate::adf::heuristics::Heuristic] allows one to choose a
|
|||||||
use adf_bdd::parser::AdfParser;
|
use adf_bdd::parser::AdfParser;
|
||||||
use adf_bdd::adf::Adf;
|
use adf_bdd::adf::Adf;
|
||||||
use adf_bdd::adf::heuristics::Heuristic;
|
use adf_bdd::adf::heuristics::Heuristic;
|
||||||
use adf_bdd::datatypes::Term;
|
use adf_bdd::datatypes::{Term, adf::VarContainer};
|
||||||
// create a channel
|
// create a channel
|
||||||
let (s, r) = crossbeam_channel::unbounded();
|
let (s, r) = crossbeam_channel::unbounded();
|
||||||
|
let variables = VarContainer::default();
|
||||||
|
let variables_worker = variables.clone();
|
||||||
// spawn a solver thread
|
// spawn a solver thread
|
||||||
let solving = std::thread::spawn(move || {
|
let solving = std::thread::spawn(move || {
|
||||||
// use the above example as input
|
// use the above example as input
|
||||||
let input = "s(a).s(b).s(c).s(d).ac(a,c(v)).ac(b,or(a,b)).ac(c,neg(b)).ac(d,d).";
|
let input = "s(a).s(b).s(c).s(d).ac(a,c(v)).ac(b,or(a,b)).ac(c,neg(b)).ac(d,d).";
|
||||||
let parser = AdfParser::default();
|
let parser = AdfParser::with_var_container(variables_worker);
|
||||||
parser.parse()(&input).expect("parsing worked well");
|
parser.parse()(&input).expect("parsing worked well");
|
||||||
// use hybrid approach
|
// use hybrid approach
|
||||||
let mut adf = adf_bdd::adfbiodivine::Adf::from_parser(&parser).hybrid_step();
|
let mut adf = adf_bdd::adfbiodivine::Adf::from_parser(&parser).hybrid_step();
|
||||||
@ -184,9 +186,12 @@ let solving = std::thread::spawn(move || {
|
|||||||
adf.stable_nogood_channel(Heuristic::Simple, s);
|
adf.stable_nogood_channel(Heuristic::Simple, s);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let printer = variables.print_dictionary();
|
||||||
// print results as they are computed
|
// print results as they are computed
|
||||||
while let Ok(result) = r.recv() {
|
while let Ok(result) = r.recv() {
|
||||||
println!("stable model: {:?}", result);
|
print!("stable model: {:?} \n", result);
|
||||||
|
// use dictionary
|
||||||
|
print!("stable model with variable names: {}", printer.print_interpretation(&result));
|
||||||
# assert_eq!(result, vec![Term(1),Term(1),Term(0),Term(0)]);
|
# assert_eq!(result, vec![Term(1),Term(1),Term(0),Term(0)]);
|
||||||
}
|
}
|
||||||
// waiting for the other thread to close
|
// waiting for the other thread to close
|
||||||
|
|||||||
@ -10,7 +10,13 @@ use nom::{
|
|||||||
sequence::{delimited, preceded, separated_pair, terminated},
|
sequence::{delimited, preceded, separated_pair, terminated},
|
||||||
IResult,
|
IResult,
|
||||||
};
|
};
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
use std::collections::HashMap;
|
||||||
|
use std::{
|
||||||
|
cell::RefCell,
|
||||||
|
sync::{Arc, RwLock},
|
||||||
|
};
|
||||||
|
|
||||||
|
use crate::datatypes::adf::VarContainer;
|
||||||
|
|
||||||
/// A representation of a formula, still using the strings from the input.
|
/// A representation of a formula, still using the strings from the input.
|
||||||
#[derive(Clone, PartialEq, Eq)]
|
#[derive(Clone, PartialEq, Eq)]
|
||||||
@ -127,8 +133,8 @@ impl std::fmt::Debug for Formula<'_> {
|
|||||||
/// Note that the parser can be utilised by an [ADF][`crate::adf::Adf`] to initialise it with minimal overhead.
|
/// Note that the parser can be utilised by an [ADF][`crate::adf::Adf`] to initialise it with minimal overhead.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct AdfParser<'a> {
|
pub struct AdfParser<'a> {
|
||||||
namelist: Rc<RefCell<Vec<String>>>,
|
namelist: Arc<RwLock<Vec<String>>>,
|
||||||
dict: Rc<RefCell<HashMap<String, usize>>>,
|
dict: Arc<RwLock<HashMap<String, usize>>>,
|
||||||
formulae: RefCell<Vec<Formula<'a>>>,
|
formulae: RefCell<Vec<Formula<'a>>>,
|
||||||
formulaname: RefCell<Vec<String>>,
|
formulaname: RefCell<Vec<String>>,
|
||||||
}
|
}
|
||||||
@ -136,8 +142,8 @@ pub struct AdfParser<'a> {
|
|||||||
impl Default for AdfParser<'_> {
|
impl Default for AdfParser<'_> {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
AdfParser {
|
AdfParser {
|
||||||
namelist: Rc::new(RefCell::new(Vec::new())),
|
namelist: Arc::new(RwLock::new(Vec::new())),
|
||||||
dict: Rc::new(RefCell::new(HashMap::new())),
|
dict: Arc::new(RwLock::new(HashMap::new())),
|
||||||
formulae: RefCell::new(Vec::new()),
|
formulae: RefCell::new(Vec::new()),
|
||||||
formulaname: RefCell::new(Vec::new()),
|
formulaname: RefCell::new(Vec::new()),
|
||||||
}
|
}
|
||||||
@ -176,8 +182,14 @@ where
|
|||||||
|
|
||||||
fn parse_statement(&'a self) -> impl FnMut(&'a str) -> IResult<&'a str, ()> {
|
fn parse_statement(&'a self) -> impl FnMut(&'a str) -> IResult<&'a str, ()> {
|
||||||
|input| {
|
|input| {
|
||||||
let mut dict = self.dict.borrow_mut();
|
let mut dict = self
|
||||||
let mut namelist = self.namelist.borrow_mut();
|
.dict
|
||||||
|
.write()
|
||||||
|
.expect("RwLock of dict could not get write access");
|
||||||
|
let mut namelist = self
|
||||||
|
.namelist
|
||||||
|
.write()
|
||||||
|
.expect("RwLock of namelist could not get write access");
|
||||||
let (remain, statement) =
|
let (remain, statement) =
|
||||||
terminated(AdfParser::statement, terminated(tag("."), multispace0))(input)?;
|
terminated(AdfParser::statement, terminated(tag("."), multispace0))(input)?;
|
||||||
if !dict.contains_key(statement) {
|
if !dict.contains_key(statement) {
|
||||||
@ -200,16 +212,31 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a> AdfParser<'a> {
|
||||||
|
/// Creates a new parser, utilising the already existing [VarContainer]
|
||||||
|
pub fn with_var_container(var_container: VarContainer) -> AdfParser<'a> {
|
||||||
|
AdfParser {
|
||||||
|
namelist: var_container.names(),
|
||||||
|
dict: var_container.mappings(),
|
||||||
|
formulae: RefCell::new(Vec::new()),
|
||||||
|
formulaname: RefCell::new(Vec::new()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl AdfParser<'_> {
|
impl AdfParser<'_> {
|
||||||
/// after an update to the namelist, all indizes are updated
|
/// after an update to the namelist, all indizes are updated
|
||||||
fn regenerate_indizes(&self) {
|
fn regenerate_indizes(&self) {
|
||||||
self.namelist
|
self.namelist
|
||||||
.as_ref()
|
.read()
|
||||||
.borrow()
|
.expect("ReadLock on namelist failed")
|
||||||
.iter()
|
.iter()
|
||||||
.enumerate()
|
.enumerate()
|
||||||
.for_each(|(i, elem)| {
|
.for_each(|(i, elem)| {
|
||||||
self.dict.as_ref().borrow_mut().insert(elem.clone(), i);
|
self.dict
|
||||||
|
.write()
|
||||||
|
.expect("WriteLock on dict failed")
|
||||||
|
.insert(elem.clone(), i);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -217,7 +244,10 @@ impl AdfParser<'_> {
|
|||||||
/// Results, which got used before might become corrupted.
|
/// Results, which got used before might become corrupted.
|
||||||
/// Ensure that all used data is physically copied.
|
/// Ensure that all used data is physically copied.
|
||||||
pub fn varsort_lexi(&self) -> &Self {
|
pub fn varsort_lexi(&self) -> &Self {
|
||||||
self.namelist.as_ref().borrow_mut().sort_unstable();
|
self.namelist
|
||||||
|
.write()
|
||||||
|
.expect("WriteLock on namelist failed")
|
||||||
|
.sort_unstable();
|
||||||
self.regenerate_indizes();
|
self.regenerate_indizes();
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -227,8 +257,8 @@ impl AdfParser<'_> {
|
|||||||
/// Ensure that all used data is physically copied.
|
/// Ensure that all used data is physically copied.
|
||||||
pub fn varsort_alphanum(&self) -> &Self {
|
pub fn varsort_alphanum(&self) -> &Self {
|
||||||
self.namelist
|
self.namelist
|
||||||
.as_ref()
|
.write()
|
||||||
.borrow_mut()
|
.expect("WriteLock on namelist failed")
|
||||||
.string_sort_unstable(natural_lexical_cmp);
|
.string_sort_unstable(natural_lexical_cmp);
|
||||||
self.regenerate_indizes();
|
self.regenerate_indizes();
|
||||||
self
|
self
|
||||||
@ -343,14 +373,18 @@ impl AdfParser<'_> {
|
|||||||
/// Allows insight of the number of parsed statements.
|
/// Allows insight of the number of parsed statements.
|
||||||
pub fn dict_size(&self) -> usize {
|
pub fn dict_size(&self) -> usize {
|
||||||
//self.dict.borrow().len()
|
//self.dict.borrow().len()
|
||||||
self.dict.as_ref().borrow().len()
|
self.dict.read().expect("ReadLock on dict failed").len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number-representation and position of a given statement in string-representation.
|
/// Returns the number-representation and position of a given statement in string-representation.
|
||||||
///
|
///
|
||||||
/// Will return [None] if the string does no occur in the dictionary.
|
/// Will return [None] if the string does no occur in the dictionary.
|
||||||
pub fn dict_value(&self, value: &str) -> Option<usize> {
|
pub fn dict_value(&self, value: &str) -> Option<usize> {
|
||||||
self.dict.as_ref().borrow().get(value).copied()
|
self.dict
|
||||||
|
.read()
|
||||||
|
.expect("ReadLock on dict failed")
|
||||||
|
.get(value)
|
||||||
|
.copied()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the acceptance condition of a statement at the given position.
|
/// Returns the acceptance condition of a statement at the given position.
|
||||||
@ -360,12 +394,17 @@ impl AdfParser<'_> {
|
|||||||
self.formulae.borrow().get(idx).cloned()
|
self.formulae.borrow().get(idx).cloned()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn dict_rc_refcell(&self) -> Rc<RefCell<HashMap<String, usize>>> {
|
pub(crate) fn dict(&self) -> Arc<RwLock<HashMap<String, usize>>> {
|
||||||
Rc::clone(&self.dict)
|
Arc::clone(&self.dict)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn namelist_rc_refcell(&self) -> Rc<RefCell<Vec<String>>> {
|
pub(crate) fn namelist(&self) -> Arc<RwLock<Vec<String>>> {
|
||||||
Rc::clone(&self.namelist)
|
Arc::clone(&self.namelist)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a [`VarContainer`][crate::datatypes::adf::VarContainer] which allows to access the variable information gathered by the parser
|
||||||
|
pub fn var_container(&self) -> VarContainer {
|
||||||
|
VarContainer::from_parser(self.namelist(), self.dict())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn formula_count(&self) -> usize {
|
pub(crate) fn formula_count(&self) -> usize {
|
||||||
@ -379,8 +418,8 @@ impl AdfParser<'_> {
|
|||||||
.map(|name| {
|
.map(|name| {
|
||||||
*self
|
*self
|
||||||
.dict
|
.dict
|
||||||
.as_ref()
|
.read()
|
||||||
.borrow()
|
.expect("ReadLock on dict failed")
|
||||||
.get(name)
|
.get(name)
|
||||||
.expect("Dictionary should contain all the used formulanames")
|
.expect("Dictionary should contain all the used formulanames")
|
||||||
})
|
})
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user