From: Skgland Date: Fri, 25 Aug 2023 23:10:49 +0000 (+0200) Subject: [WIP] make AtomTable concurrentcy ready X-Git-Tag: remove~112^2~9 X-Git-Url: https://git.sagredo.dev/?a=commitdiff_plain;h=86166dbf25d5b6a1ee186a5a0ec97f41f1c9fd34;p=scryer-prolog.git [WIP] make AtomTable concurrentcy ready --- diff --git a/Cargo.toml b/Cargo.toml index 94f589d0..d38c6355 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ repl = ["dep:crossterm", "dep:ctrlc", "dep:rustyline"] hostname = ["dep:hostname"] tls = ["dep:native-tls"] http = ["dep:hyper", "dep:reqwest"] +rust_beta_channel = [] [build-dependencies] indexmap = "1.0.2" diff --git a/src/arena.rs b/src/arena.rs index c58db7a5..0ecec650 100644 --- a/src/arena.rs +++ b/src/arena.rs @@ -965,8 +965,8 @@ mod tests { let f_atom = atom!("f"); let g_atom = atom!("g"); - assert_eq!(f_atom.as_str(), "f"); - assert_eq!(g_atom.as_str(), "g"); + assert_eq!(&*f_atom.as_str(), "f"); + assert_eq!(&*g_atom.as_str(), "g"); let f_atom_cell = atom_as_cell!(f_atom); let g_atom_cell = atom_as_cell!(g_atom); @@ -976,7 +976,7 @@ mod tests { match f_atom_cell.to_atom() { Some(atom) => { assert_eq!(f_atom, atom); - assert_eq!(atom.as_str(), "f"); + assert_eq!(&*atom.as_str(), "f"); } None => { assert!(false); @@ -987,7 +987,7 @@ mod tests { (HeapCellValueTag::Atom, (atom, arity)) => { assert_eq!(f_atom, atom); assert_eq!(arity, 0); - assert_eq!(atom.as_str(), "f"); + assert_eq!(&*atom.as_str(), "f"); } _ => { unreachable!() } ); @@ -996,7 +996,7 @@ mod tests { (HeapCellValueTag::Atom, (atom, arity)) => { assert_eq!(g_atom, atom); assert_eq!(arity, 0); - assert_eq!(atom.as_str(), "g"); + assert_eq!(&*atom.as_str(), "g"); } _ => { unreachable!() } ); @@ -1006,7 +1006,7 @@ mod tests { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "ronan", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -1014,7 +1014,7 @@ mod tests { match pstr_cell.to_pstr() { Some(pstr) => { - assert_eq!(pstr.as_str_from(0), "ronan"); + assert_eq!(&*pstr.as_str_from(0), "ronan"); } None => { assert!(false); @@ -1024,7 +1024,7 @@ mod tests { read_heap_cell!(pstr_cell, (HeapCellValueTag::PStr, pstr_atom) => { let pstr = PartialString::from(pstr_atom); - assert_eq!(pstr.as_str_from(0), "ronan"); + assert_eq!(&*pstr.as_str_from(0), "ronan"); } _ => { unreachable!() } ); @@ -1133,7 +1133,7 @@ mod tests { read_heap_cell!(cell, (HeapCellValueTag::Atom, (el, _arity)) => { assert_eq!(el.flat_index(), empty_list_as_cell!().get_value()); - assert_eq!(el.as_str(), "[]"); + assert_eq!(&*el.as_str(), "[]"); } _ => { unreachable!() } ); diff --git a/src/atom_table.rs b/src/atom_table.rs index f3b91a58..704bc523 100644 --- a/src/atom_table.rs +++ b/src/atom_table.rs @@ -2,17 +2,22 @@ use crate::parser::ast::MAX_ARITY; use crate::raw_block::*; use crate::types::*; -use std::borrow::Borrow; use std::cmp::Ordering; use std::hash::{Hash, Hasher}; use std::mem; +use std::ops::Deref; use std::ptr; use std::slice; use std::str; +use std::sync::Arc; +use std::sync::Weak; use indexmap::IndexSet; use modular_bitfield::prelude::*; +use tokio::runtime::Handle; +use tokio::sync::OwnedRwLockReadGuard; +use tokio::sync::RwLock; #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub struct Atom { @@ -41,63 +46,31 @@ impl From for Atom { } } -const ATOM_TABLE_INIT_SIZE: usize = 1 << 16; -const ATOM_TABLE_ALIGN: usize = 8; - -#[cfg(test)] -thread_local! { - static ATOM_TABLE_BUF_BASE: std::cell::RefCell<*const u8> = std::cell::RefCell::new(ptr::null_mut()); +impl indexmap::Equivalent for str { + fn equivalent(&self, atom: &Atom) -> bool { + &*atom.as_str() == self + } } -#[cfg(not(test))] -static ATOM_TABLE_BUF_BASE: std::sync::atomic::AtomicPtr = - std::sync::atomic::AtomicPtr::new(ptr::null_mut()); - -fn set_atom_tbl_buf_base(old_ptr: *const u8, new_ptr: *const u8) -> Result<(), *const u8> { - #[cfg(test)] - { - ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| { - let mut borrow = atom_table_buf_base.borrow_mut(); - if *borrow != old_ptr { - Err(*borrow) - } else { - *borrow = new_ptr; - Ok(()) - } - })?; - }; - #[cfg(not(test))] - { - ATOM_TABLE_BUF_BASE - .compare_exchange( - old_ptr.cast_mut(), - new_ptr.cast_mut(), - std::sync::atomic::Ordering::Relaxed, - std::sync::atomic::Ordering::Relaxed, - ) - .map_err(|ptr| ptr.cast_const()) - }?; - Ok(()) -} +const ATOM_TABLE_INIT_SIZE: usize = 1 << 16; +const ATOM_TABLE_ALIGN: usize = 8; -pub(crate) fn get_atom_tbl_buf_base() -> *const u8 { - #[cfg(test)] +pub fn global_atom_table() -> &'static RwLock>> { + #[cfg(feature = "rust_beta_channel")] { - ATOM_TABLE_BUF_BASE.with(|atom_table_buf_base| *atom_table_buf_base.borrow()) + // const Weak::new will be stabilized in 1.73 which is currently in beta, + // till then we need a OnceLock for initialization + static GLOBAL_ATOM_TABLE: RwLock>> = RwLock::new(Weak::new()); + &GLOBAL_ATOM_TABLE } - #[cfg(not(test))] + #[cfg(not(feature = "rust_beta_channel"))] { - ATOM_TABLE_BUF_BASE.load(std::sync::atomic::Ordering::Relaxed) + use std::sync::OnceLock; + static GLOBAL_ATOM_TABLE: OnceLock>>> = OnceLock::new(); + GLOBAL_ATOM_TABLE.get_or_init(|| RwLock::new(Weak::new())) } } -#[test] -#[should_panic(expected = "Overwriting atom table base pointer")] -fn atomtable_is_not_concurrency_safe() { - let _table_a = AtomTable::new(); - let _table_b = AtomTable::new(); -} - impl RawBlockTraits for AtomTable { #[inline] fn init_size() -> usize { @@ -126,13 +99,6 @@ impl AtomHeader { } } -impl Borrow for Atom { - #[inline] - fn borrow(&self) -> &str { - self.as_str() - } -} - impl Hash for Atom { #[inline] fn hash(&self, hasher: &mut H) { @@ -148,16 +114,68 @@ macro_rules! is_char { }; } -impl Atom { - #[inline] - pub fn buf(self) -> *const u8 { - let ptr = self.as_ptr(); +pub enum AtomString<'a> { + Static(&'a str), + Dynamic(OwnedRwLockReadGuard), +} + +impl AtomString<'_> { + pub fn map(self, f: F) -> Self + where + for<'a> F: FnOnce(&'a str) -> &'a str, + { + match self { + Self::Static(reference) => Self::Static(f(reference)), + Self::Dynamic(guard) => Self::Dynamic(OwnedRwLockReadGuard::map(guard, f)), + } + } +} - if ptr.is_null() { - return ptr::null(); +impl std::fmt::Debug for AtomString<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Debug::fmt(self.deref(), f) + } +} + +impl std::fmt::Display for AtomString<'_> { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + std::fmt::Display::fmt(self.deref(), f) + } +} + +impl std::ops::Deref for AtomString<'_> { + type Target = str; + fn deref(&self) -> &Self::Target { + match self { + Self::Static(reference) => reference, + Self::Dynamic(guard) => guard.deref(), } + } +} - (ptr as usize + mem::size_of::()) as *const u8 +impl rustyline::completion::Candidate for AtomString<'_> { + fn display(&self) -> &str { + self.deref() + } + + fn replacement(&self) -> &str { + self.deref() + } +} + +impl Atom { + #[inline] + pub fn buf(self) -> Option> { + if let Some(guard) = self.as_ptr() { + Some(OwnedRwLockReadGuard::map(guard, |ptr| unsafe { + (ptr as *const u8) + .offset(mem::size_of::() as isize) + .as_ref() + .unwrap() + })) + } else { + None + } } #[inline(always)] @@ -166,12 +184,36 @@ impl Atom { } #[inline(always)] - pub fn as_ptr(self) -> *const u8 { + pub fn as_ptr(self) -> Option> { if self.is_static() { - ptr::null() + None } else { - (get_atom_tbl_buf_base() as usize + (self.index as usize) - (STRINGS.len() << 3)) - as *const u8 + let atom_table = global_atom_table() + .blocking_read() + .upgrade() + .expect("We should only have an Atom while there is an AtomTable"); + + #[cfg(not(test))] + let guard = Handle::current().block_on(atom_table.read_owned()); + + #[cfg(test)] + let guard = { + if let Ok(handle) = Handle::try_current() { + handle.block_on(atom_table.read_owned()) + } else { + tokio::runtime::Runtime::new() + .unwrap() + .block_on(atom_table.read_owned()) + } + }; + + Some(OwnedRwLockReadGuard::map(guard, |atom_table| unsafe { + atom_table + .buf() + .offset(((self.index as usize) - (STRINGS.len() << 3)) as isize) + .as_ref() + .unwrap() + })) } } @@ -185,7 +227,10 @@ impl Atom { if self.is_static() { STRINGS[(self.index >> 3) as usize].len() } else { - unsafe { ptr::read(self.as_ptr() as *const AtomHeader).len() as _ } + unsafe { + ptr::read(self.as_ptr().unwrap().deref() as *const u8 as *const AtomHeader).len() + as _ + } } } @@ -209,24 +254,20 @@ impl Atom { } #[inline] - pub fn chars(&self) -> str::Chars { - self.as_str().chars() - } - - #[inline] - pub fn as_str(&self) -> &str { - unsafe { - let ptr = self.as_ptr(); - - if ptr.is_null() { - return STRINGS[(self.index >> 3) as usize]; - } - - let header = ptr::read::(ptr as *const _); - let len = header.len() as usize; - let buf = (ptr as usize + mem::size_of::()) as *mut u8; - - str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) + pub fn as_str(&self) -> AtomString<'static> { + if let Some(ptr_guard) = self.as_ptr() { + AtomString::Dynamic(OwnedRwLockReadGuard::map(ptr_guard, |ptr| { + let header = + unsafe { ptr::read::(ptr as *const u8 as *const AtomHeader) }; + let len = header.len() as usize; + let buf = + (unsafe { (ptr as *const u8).offset(mem::size_of::() as isize) }) + as *mut u8; + + unsafe { str::from_utf8_unchecked(slice::from_raw_parts(buf, len)) } + })) + } else { + return AtomString::Static(STRINGS[(self.index >> 3) as usize]); } } @@ -259,7 +300,7 @@ impl PartialOrd for Atom { impl Ord for Atom { #[inline] fn cmp(&self, other: &Atom) -> Ordering { - self.as_str().cmp(other.as_str()) + self.as_str().cmp(&*other.as_str()) } } @@ -269,34 +310,32 @@ pub struct AtomTable { pub table: IndexSet, } -#[cold] -fn atom_table_base_pointer_mismatch(expected: *const u8, got: *const u8) -> ! { - assert_eq!(expected, got, "Overwriting atom table base pointer, expected old value to be {expected:p}, but found {got:p}"); - unreachable!("This should only be called in a case of a mismatch as such the assert_eq should have failed!") -} - impl Drop for AtomTable { fn drop(&mut self) { - if let Err(got) = set_atom_tbl_buf_base(self.block.base, ptr::null()) { - atom_table_base_pointer_mismatch(self.block.base, got); - } self.block.deallocate(); } } impl AtomTable { #[inline] - pub fn new() -> Self { - let mut block = RawBlock::new(); - - if let Err(got) = set_atom_tbl_buf_base(ptr::null(), block.base) { - block.deallocate(); - atom_table_base_pointer_mismatch(ptr::null(), got); - } - - Self { - block, - table: IndexSet::new(), + pub fn new() -> Arc> { + let upgraded = global_atom_table().blocking_read().upgrade(); + // don't inline upgraded, temporary will be dropped too late in case of None + if let Some(atom_table) = upgraded { + atom_table + } else { + let mut guard = global_atom_table().blocking_write(); + // try to upgrade again in case we lost the race on the write lock + if let Some(atom_table) = guard.upgrade() { + atom_table + } else { + let atom_table = Arc::new(RwLock::new(Self { + block: RawBlock::new(), + table: IndexSet::new(), + })); + *guard = Arc::downgrade(&atom_table); + atom_table + } } } @@ -328,24 +367,14 @@ impl AtomTable { let align_offset = 8 * mem::align_of::(); let size = (size & !(align_offset - 1)) + align_offset; - let len_ptr = { - let mut ptr; - - loop { - ptr = self.block.alloc(size); - - if ptr.is_null() { - let old_base = self.block.base; - self.block.grow(); - if let Err(got) = set_atom_tbl_buf_base(old_base, self.block.base) { - atom_table_base_pointer_mismatch(old_base, got); - } - } else { - break; - } - } + let len_ptr = loop { + let ptr = self.block.alloc(size); - ptr + if ptr.is_null() { + self.block.grow(); + } else { + break ptr; + } }; let ptr_base = self.block.base as usize; @@ -363,6 +392,9 @@ impl AtomTable { } } +unsafe impl Send for AtomTable {} +unsafe impl Sync for AtomTable {} + #[bitfield] #[repr(u64)] #[derive(Copy, Clone, Debug)] diff --git a/src/codegen.rs b/src/codegen.rs index 685077ba..ca4e2604 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -18,6 +18,8 @@ use crate::machine::machine_errors::*; use fxhash::FxBuildHasher; use indexmap::IndexSet; +use tokio::sync::RwLock; + use std::cell::Cell; use std::collections::VecDeque; @@ -262,7 +264,7 @@ impl CodeGenSettings { #[derive(Debug)] pub(crate) struct CodeGenerator<'a> { - pub(crate) atom_tbl: &'a mut AtomTable, + pub(crate) atom_tbl: &'a RwLock, marker: DebrayAllocator, settings: CodeGenSettings, pub(crate) skeleton: PredicateSkeleton, @@ -362,7 +364,7 @@ fn structure_cell(term: &Term) -> Option<&Cell> { } impl<'b> CodeGenerator<'b> { - pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self { + pub(crate) fn new(atom_tbl: &'b RwLock, settings: CodeGenSettings) -> Self { CodeGenerator { atom_tbl, marker: DebrayAllocator::new(), @@ -509,7 +511,7 @@ impl<'b> CodeGenerator<'b> { TermRef::PartialString(lvl, cell, string, tail) => { self.marker .mark_non_var::(lvl, term_loc, cell, &mut target); - let atom = self.atom_tbl.build_with(&string); + let atom = self.atom_tbl.blocking_write().build_with(&string); target.push_back(Target::to_pstr(lvl, atom, cell.get(), true)); self.subterm_to_instr::(tail, term_loc, &mut target); @@ -1240,7 +1242,12 @@ impl<'b> CodeGenerator<'b> { let index = code.len(); if clauses_len > 1 || self.settings.is_extensible { - code_offsets.index_term(arg, index, &mut clause_index_info, self.atom_tbl); + code_offsets.index_term( + arg, + index, + &mut clause_index_info, + &mut self.atom_tbl.blocking_write(), + ); } } diff --git a/src/ffi.rs b/src/ffi.rs index d8553315..8fd55dbc 100644 --- a/src/ffi.rs +++ b/src/ffi.rs @@ -101,7 +101,7 @@ impl ForeignFunctionTable { atom!("ptr") => &mut types::pointer, atom!("f32") => &mut types::float, atom!("f64") => &mut types::double, - struct_name => match self.structs.get_mut(struct_name.as_str()) { + struct_name => match self.structs.get_mut(&*struct_name.as_str()) { Some(ref mut struct_type) => &mut struct_type.ffi_type, None => unreachable!(), }, @@ -437,11 +437,11 @@ impl ForeignFunctionTable { let substruct = struct_type.atom_fields[i].as_str(); let struct_type = self .structs - .get(substruct) + .get(&*substruct) .ok_or(FFIError::StructNotFound)?; field_ptr = field_ptr .add(field_ptr.align_offset(struct_type.ffi_type.alignment as usize)); - let struct_val = self.read_struct(field_ptr, substruct, struct_type); + let struct_val = self.read_struct(field_ptr, &*substruct, struct_type); returns.push(struct_val?); field_ptr = field_ptr.add(struct_type.ffi_type.size); } diff --git a/src/forms.rs b/src/forms.rs index 0912fbe9..54e5dd45 100644 --- a/src/forms.rs +++ b/src/forms.rs @@ -290,7 +290,7 @@ impl ClauseInfo for Term { fn arity(&self) -> usize { match self { - Term::Clause(_, name, terms) => match name.as_str() { + Term::Clause(_, name, terms) => match &*name.as_str() { ":-" => match terms.len() { 1 => 0, 2 => terms[0].arity(), @@ -489,11 +489,11 @@ impl AtomOrString { } #[inline] - pub fn as_str(&self) -> &str { + pub fn as_str(&self) -> AtomString<'_> { match self { - AtomOrString::Atom(atom) if atom == &atom!("[]") => "", + AtomOrString::Atom(atom) if atom == &atom!("[]") => AtomString::Static(""), AtomOrString::Atom(atom) => atom.as_str(), - AtomOrString::String(string) => string.as_str(), + AtomOrString::String(string) => AtomString::Static(string.as_str()), } } diff --git a/src/heap_iter.rs b/src/heap_iter.rs index caf72439..e1a2d0a1 100644 --- a/src/heap_iter.rs +++ b/src/heap_iter.rs @@ -711,7 +711,7 @@ mod tests { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -736,7 +736,7 @@ mod tests { let pstr_second_var_cell = put_partial_string( &mut wam.machine_st.heap, "def", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; @@ -1779,7 +1779,7 @@ mod tests { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -1807,7 +1807,7 @@ mod tests { let pstr_second_var_cell = put_partial_string( &mut wam.machine_st.heap, "def", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; @@ -2378,7 +2378,7 @@ mod tests { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -2405,7 +2405,7 @@ mod tests { let pstr_second_var_cell = put_partial_string( &mut wam.machine_st.heap, "def", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; @@ -2841,7 +2841,7 @@ mod tests { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -2865,7 +2865,7 @@ mod tests { let pstr_second_var_cell = put_partial_string( &mut wam.machine_st.heap, "def", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; diff --git a/src/heap_print.rs b/src/heap_print.rs index 759cf1ed..8cd175fa 100644 --- a/src/heap_print.rs +++ b/src/heap_print.rs @@ -24,11 +24,14 @@ use ordered_float::OrderedFloat; use indexmap::IndexMap; +use tokio::sync::RwLock; + use std::cell::Cell; use std::convert::TryFrom; use std::iter::once; use std::net::{IpAddr, TcpListener}; use std::rc::Rc; +use std::sync::Arc; /* contains the location, name, precision and Specifier of the parent op. */ #[derive(Debug, Copy, Clone)] @@ -74,7 +77,7 @@ fn needs_bracketing(child_desc: OpDesc, op: &DirectedOp) -> bool { DirectedOp::Left(name, cell) => { let (priority, spec) = cell.get(); - if name.as_str() == "-" { + if &*name.as_str() == "-" { let child_assoc = child_desc.get_spec(); if is_prefix!(spec) && (is_postfix!(child_assoc) || is_infix!(child_assoc)) { return true; @@ -480,7 +483,7 @@ pub fn fmt_float(mut fl: f64) -> String { pub struct HCPrinter<'a, Outputter> { outputter: Outputter, iter: StackfulPreOrderHeapIter<'a>, - atom_tbl: &'a mut AtomTable, + atom_tbl: Arc>, op_dir: &'a OpDir, state_stack: Vec, toplevel_spec: Option, @@ -549,7 +552,7 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { pub fn new( heap: &'a mut Heap, - atom_tbl: &'a mut AtomTable, + atom_tbl: Arc>, stack: &'a mut Stack, op_dir: &'a OpDir, output: Outputter, @@ -631,7 +634,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { self.state_stack.push(TokenOrRedirect::Op(name, spec)); } } else { - match name.as_str() { + match &*name.as_str() { "|" => { self.format_bar_separator_op(max_depth, name, spec); return; @@ -894,7 +897,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { } fn print_impromptu_atom(&mut self, atom: Atom) { - let result = self.print_op_addendum(atom.as_str()); + let result = self.print_op_addendum(&*atom.as_str()); push_space_if_amb!(self, result.as_str(), { append_str!(self, &result); @@ -1405,7 +1408,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { for op in &[op, parent_op] { if let Some(ref op) = &op { if op.is_left() - && (op.is_prefix() || requires_space(op.as_atom().as_str(), "(")) + && (op.is_prefix() || requires_space(&*op.as_atom().as_str(), "(")) { self.state_stack.push(TokenOrRedirect::Space); return; @@ -1530,7 +1533,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { max_depth, ); } else { - push_space_if_amb!(printer, name.as_str(), { + push_space_if_amb!(printer, &*name.as_str(), { printer.format_clause(max_depth, arity, name, None); }); } @@ -1551,7 +1554,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { result.push('('); } - result += &printer.print_op_addendum(name.as_str()); + result += &printer.print_op_addendum(&*name.as_str()); if op.is_some() { result.push(')'); @@ -1561,7 +1564,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { append_str!(printer, &result); }); } else { - push_space_if_amb!(printer, name.as_str(), { + push_space_if_amb!(printer, &*name.as_str(), { printer.print_impromptu_atom(name); }); } @@ -1585,7 +1588,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { print_struct(self, name, arity); } (HeapCellValueTag::Char, c) => { - let name = self.atom_tbl.build_with(&String::from(c)); + let name = self.atom_tbl.blocking_write().build_with(&String::from(c)); print_struct(self, name, 0); } (HeapCellValueTag::Str, s) => { @@ -1603,7 +1606,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { max_depth, ); } else { - push_space_if_amb!(self, name.as_str(), { + push_space_if_amb!(self, &*name.as_str(), { self.format_clause(max_depth, arity, name, None); }); } @@ -1686,7 +1689,7 @@ impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> { TokenOrRedirect::BarAsOp => append_str!(self, " | "), TokenOrRedirect::Char(c) => print_char!(self, self.quoted, c), TokenOrRedirect::Op(atom, op) => { - self.print_op(atom.as_str()); + self.print_op(&*atom.as_str()); if is_prefix!(op.get_spec()) { self.set_parent_of_first_op(Some(DirectedOp::Left(atom, op))); @@ -1762,7 +1765,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1791,7 +1794,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1815,7 +1818,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1828,7 +1831,7 @@ mod tests { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1861,7 +1864,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1880,7 +1883,7 @@ mod tests { { let printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1897,7 +1900,7 @@ mod tests { { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1929,7 +1932,7 @@ mod tests { { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1950,13 +1953,13 @@ mod tests { put_partial_string( &mut wam.machine_st.heap, "abc", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); { let printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), @@ -1984,7 +1987,7 @@ mod tests { { let mut printer = HCPrinter::new( &mut wam.machine_st.heap, - &mut wam.machine_st.atom_tbl, + Arc::clone(&wam.machine_st.atom_tbl), &mut wam.machine_st.stack, &wam.op_dir, PrinterOutputter::new(), diff --git a/src/machine/compile.rs b/src/machine/compile.rs index 2c6ee808..c8bf3451 100644 --- a/src/machine/compile.rs +++ b/src/machine/compile.rs @@ -1240,6 +1240,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { return Some( LS::machine_st(&mut self.payload) .atom_tbl + .blocking_write() .build_with(path_str), ); } @@ -1259,7 +1260,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let clause = self.try_term_to_tl(term, &mut preprocessor)?; // let queue = preprocessor.parse_queue(self)?; - let mut cg = CodeGenerator::new(&mut LS::machine_st(&mut self.payload).atom_tbl, settings); + let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings); let clause_code = cg.compile_predicate(vec![clause])?; @@ -1289,7 +1290,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { clauses.push(self.try_term_to_tl(term, &mut preprocessor)?); } - let mut cg = CodeGenerator::new(&mut LS::machine_st(&mut self.payload).atom_tbl, settings); + let mut cg = CodeGenerator::new(&LS::machine_st(&mut self.payload).atom_tbl, settings); let mut code = cg.compile_predicate(clauses)?; diff --git a/src/machine/copier.rs b/src/machine/copier.rs index 093cb735..6b15298f 100644 --- a/src/machine/copier.rs +++ b/src/machine/copier.rs @@ -409,7 +409,7 @@ mod tests { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -419,7 +419,7 @@ mod tests { let pstr_second_var_cell = put_partial_string( &mut wam.machine_st.heap, "def", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; diff --git a/src/machine/gc.rs b/src/machine/gc.rs index eb5d86df..2160fc59 100644 --- a/src/machine/gc.rs +++ b/src/machine/gc.rs @@ -647,7 +647,7 @@ mod tests { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -672,7 +672,7 @@ mod tests { let pstr_second_var_cell = put_partial_string( &mut wam.machine_st.heap, "def", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; diff --git a/src/machine/load_state.rs b/src/machine/load_state.rs index 92cca660..fd857f3d 100644 --- a/src/machine/load_state.rs +++ b/src/machine/load_state.rs @@ -1150,7 +1150,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { pub(crate) fn use_module(&mut self, module_src: ModuleSource) -> Result<(), SessionError> { let (stream, listing_src) = match module_src { ModuleSource::File(filename) => { - let mut path_buf = PathBuf::from(filename.as_str()); + let mut path_buf = PathBuf::from(&*filename.as_str()); path_buf.set_extension("pl"); let file = File::open(&path_buf)?; @@ -1164,7 +1164,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { ListingSource::File(filename, path_buf), ) } - ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) { + ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) { Some(code) => { if let Some(ref module) = self.wam_prelude.indices.modules.get(&library) { if let ListingSource::DynamicallyGenerated = &module.listing_src { @@ -1232,7 +1232,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { ) -> Result<(), SessionError> { let (stream, listing_src) = match module_src { ModuleSource::File(filename) => { - let mut path_buf = PathBuf::from(filename.as_str()); + let mut path_buf = PathBuf::from(&*filename.as_str()); path_buf.set_extension("pl"); let file = File::open(&path_buf)?; @@ -1245,7 +1245,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { ListingSource::File(filename, path_buf), ) } - ModuleSource::Library(library) => match LIBRARIES.borrow().get(library.as_str()) { + ModuleSource::Library(library) => match LIBRARIES.borrow().get(&*library.as_str()) { Some(code) => { if self.wam_prelude.indices.modules.contains_key(&library) { return self.import_qualified_module(library, exports); diff --git a/src/machine/loader.rs b/src/machine/loader.rs index c42610a5..d42f923c 100644 --- a/src/machine/loader.rs +++ b/src/machine/loader.rs @@ -1076,7 +1076,7 @@ impl<'a, LS: LoadState<'a>> Loader<'a, LS> { let export_list = machine_st.read_term_from_heap(cell)?; let atom_tbl = &mut LS::machine_st(&mut self.payload).atom_tbl; - let export_list = setup_module_export_list(export_list, atom_tbl)?; + let export_list = setup_module_export_list(export_list, &mut atom_tbl.blocking_write())?; Ok(export_list.into_iter().collect()) } @@ -1420,7 +1420,7 @@ impl MachineState { term_stack.push(Term::PartialString(Cell::default(), string, tail)); } Ok((string, None)) => { - let atom = self.atom_tbl.build_with(&string); + let atom = self.atom_tbl.blocking_write().build_with(&string); term_stack.push(Term::CompleteString(Cell::default(), atom)); } Err(cons_term) => term_stack.push(cons_term), @@ -1855,7 +1855,7 @@ impl Machine { .store(self.machine_st.deref(self.machine_st.registers[2]))); self.load_contexts - .push(LoadContext::new(path.as_str(), stream)); + .push(LoadContext::new(&*path.as_str(), stream)); Ok(()) } @@ -1917,7 +1917,11 @@ impl Machine { pub(crate) fn load_context_source(&mut self) { if let Some(load_context) = self.load_contexts.last() { let path_str = load_context.path.to_str().unwrap(); - let path_atom = self.machine_st.atom_tbl.build_with(path_str); + let path_atom = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(path_str); self.machine_st .unify_atom(path_atom, self.machine_st.registers[1]); @@ -1931,7 +1935,11 @@ impl Machine { match load_context.path.file_name() { Some(file_name) if load_context.path.is_file() => { let file_name_str = file_name.to_str().unwrap(); - let file_name_atom = self.machine_st.atom_tbl.build_with(file_name_str); + let file_name_atom = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(file_name_str); self.machine_st .unify_atom(file_name_atom, self.machine_st.registers[1]); @@ -1950,7 +1958,11 @@ impl Machine { if let Some(load_context) = self.load_contexts.last() { if let Some(directory) = load_context.path.parent() { let directory_str = directory.to_str().unwrap(); - let directory_atom = self.machine_st.atom_tbl.build_with(directory_str); + let directory_atom = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(directory_str); self.machine_st .unify_atom(directory_atom, self.machine_st.registers[1]); diff --git a/src/machine/machine_state.rs b/src/machine/machine_state.rs index 4e344844..c5ae21a4 100644 --- a/src/machine/machine_state.rs +++ b/src/machine/machine_state.rs @@ -18,10 +18,12 @@ use crate::types::*; use crate::parser::dashu::Integer; use indexmap::IndexMap; +use tokio::sync::RwLock; use std::convert::TryFrom; use std::fmt; use std::ops::{Index, IndexMut}; +use std::sync::Arc; pub(crate) type Registers = [HeapCellValue; MAX_ARITY + 1]; @@ -57,7 +59,7 @@ pub enum OnEOF { } pub struct MachineState { - pub atom_tbl: AtomTable, + pub atom_tbl: Arc>, pub arena: Arena, pub(super) pdl: Vec, pub(super) s: HeapPtr, @@ -529,7 +531,7 @@ impl MachineState { Some((var_name, var)) } }), - &mut self.atom_tbl, + &mut self.atom_tbl.blocking_write(), ); let singleton_addr = self.registers[3]; @@ -615,7 +617,7 @@ impl MachineState { false } }), - &mut self.atom_tbl, + &mut self.atom_tbl.blocking_write(), ); for var in term_write_result.var_dict.values_mut() { @@ -657,12 +659,10 @@ impl MachineState { stream: Stream, indices: &mut IndexStore, ) -> CallResult { - let atoms_ptr = (&self.atom_tbl.table) as *const indexmap::IndexSet; - if let Stream::Readline(ptr) = stream { unsafe { let readline = ptr.as_ptr().as_mut().unwrap(); - readline.set_atoms_for_completion(atoms_ptr); + readline.set_atoms_for_completion(&self.atom_tbl); return self.read_term( stream, indices, @@ -776,14 +776,14 @@ impl MachineState { } (HeapCellValueTag::Atom, (name, _arity)) => { debug_assert_eq!(_arity, 0); - var_names.insert(var, VarPtr::from(name.as_str())); + var_names.insert(var, VarPtr::from(&*name.as_str())); } (HeapCellValueTag::Str, s) => { let (name, arity) = cell_as_atom_cell!(self.heap[s]) .get_name_and_arity(); debug_assert_eq!(arity, 0); - var_names.insert(var, VarPtr::from(name.as_str())); + var_names.insert(var, VarPtr::from(&*name.as_str())); } _ => { unreachable!(); @@ -864,7 +864,7 @@ impl MachineState { let mut printer = HCPrinter::new( &mut self.heap, - &mut self.atom_tbl, + Arc::clone(&self.atom_tbl), &mut self.stack, op_dir, PrinterOutputter::new(), diff --git a/src/machine/machine_state_impl.rs b/src/machine/machine_state_impl.rs index 964e30bb..991cccfa 100644 --- a/src/machine/machine_state_impl.rs +++ b/src/machine/machine_state_impl.rs @@ -503,7 +503,7 @@ impl MachineState { } else { self.pdl.clear(); return Some( - n1.chars().next().cmp(&Some(c2)) + n1.as_str().chars().next().cmp(&Some(c2)) .then(Ordering::Greater) ); } @@ -533,7 +533,7 @@ impl MachineState { } else { self.pdl.clear(); return Some( - Some(c1).cmp(&n2.chars().next()) + Some(c1).cmp(&n2.as_str().chars().next()) .then(Ordering::Less) ); } @@ -556,7 +556,7 @@ impl MachineState { } else { self.pdl.clear(); return Some( - Some(c1).cmp(&n2.chars().next()) + Some(c1).cmp(&n2.as_str().chars().next()) .then(Ordering::Less) ); } @@ -586,7 +586,7 @@ impl MachineState { } else { self.pdl.clear(); return Some( - n1.chars().next().cmp(&Some(c2)) + n1.as_str().chars().next().cmp(&Some(c2)) .then(Ordering::Greater) ); } @@ -896,7 +896,7 @@ impl MachineState { let s = string.as_str(); - match heap_pstr_iter.compare_pstr_to_string(s) { + match heap_pstr_iter.compare_pstr_to_string(&*s) { Some(PStrPrefixCmpResult { focus, offset, @@ -1003,9 +1003,9 @@ impl MachineState { self.s_offset = 0; self.mode = MachineMode::Read; - put_partial_string(&mut self.heap, pstr, &mut self.atom_tbl) + put_partial_string(&mut self.heap, pstr, &mut self.atom_tbl.blocking_write()) } else { - put_complete_string(&mut self.heap, pstr, &mut self.atom_tbl) + put_complete_string(&mut self.heap, pstr, &mut self.atom_tbl.blocking_write()) } } @@ -1097,7 +1097,7 @@ impl MachineState { (name, 0, 0) } (HeapCellValueTag::Char, c) => { - (self.atom_tbl.build_with(&c.to_string()), 0, 0) + (self.atom_tbl.blocking_write().build_with(&c.to_string()), 0, 0) } (HeapCellValueTag::Var | HeapCellValueTag::AttrVar | HeapCellValueTag::StackVar) => { let stub = functor_stub(atom!("call"), arity + 1); @@ -1436,7 +1436,7 @@ impl MachineState { } } (HeapCellValueTag::Char, c) => { - let c = self.atom_tbl.build_with(&c.to_string()); + let c = self.atom_tbl.blocking_write().build_with(&c.to_string()); self.try_functor_fabricate_struct( c, diff --git a/src/machine/mock_wam.rs b/src/machine/mock_wam.rs index 69b04139..7be95fbd 100644 --- a/src/machine/mock_wam.rs +++ b/src/machine/mock_wam.rs @@ -11,6 +11,8 @@ pub use crate::parser::ast::*; use crate::read::*; pub use crate::types::*; +use std::sync::Arc; + #[cfg(test)] use crate::machine::copier::CopierTarget; @@ -61,7 +63,7 @@ impl MockWAM { let mut printer = HCPrinter::new( &mut self.machine_st.heap, - &mut self.machine_st.atom_tbl, + Arc::clone(&self.machine_st.atom_tbl), &mut self.machine_st.stack, &self.op_dir, PrinterOutputter::new(), diff --git a/src/machine/mod.rs b/src/machine/mod.rs index 009a9ba5..d67fc861 100644 --- a/src/machine/mod.rs +++ b/src/machine/mod.rs @@ -230,7 +230,8 @@ impl Machine { pub fn load_file(&mut self, path: &str, stream: Stream) { self.machine_st.registers[1] = stream_as_cell!(stream); - self.machine_st.registers[2] = atom_as_cell!(self.machine_st.atom_tbl.build_with(path)); + self.machine_st.registers[2] = + atom_as_cell!(self.machine_st.atom_tbl.blocking_write().build_with(path)); self.run_module_predicate(atom!("loader"), (atom!("file_load"), 2)); } @@ -295,7 +296,7 @@ impl Machine { arg_pstrs.push(put_complete_string( &mut self.machine_st.heap, &arg, - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), )); } diff --git a/src/machine/partial_string.rs b/src/machine/partial_string.rs index 3cdd03ec..5605474d 100644 --- a/src/machine/partial_string.rs +++ b/src/machine/partial_string.rs @@ -55,8 +55,8 @@ impl PartialString { } #[inline(always)] - pub(crate) fn as_str_from(&self, n: usize) -> &str { - &self.0.as_str()[n..] + pub(crate) fn as_str_from(&self, n: usize) -> AtomString { + self.0.as_str().map(|str| &str[n..]) } } @@ -155,7 +155,7 @@ impl<'a> HeapPStrIter<'a> { let s = &s[result.prefix_len..]; if s.len() >= t.len() { - if s.starts_with(t) { + if (&*s).starts_with(&*t) { result.prefix_len += t.len(); result.offset += t.len(); } else { @@ -229,7 +229,7 @@ impl<'a> HeapPStrIter<'a> { } PStrIteratee::PStrSegment(_, pstr_atom, n) => { let pstr = PartialString::from(pstr_atom); - buf += pstr.as_str_from(n); + buf += &*pstr.as_str_from(n); } } } @@ -714,7 +714,7 @@ pub fn compare_pstr_prefixes<'a>( let str2 = pstr2.as_str_from(n2); match str1.len().cmp(&str2.len()) { - Ordering::Equal if str1 == str2 => { + Ordering::Equal if &*str1 == &*str2 => { cycle_detection_step(i1, i2, &step_1); let both_cyclic = cycle_detection_step(i2, i1, &step_2); @@ -725,7 +725,7 @@ pub fn compare_pstr_prefixes<'a>( continue; } } - Ordering::Less if str2.starts_with(str1) => { + Ordering::Less if str2.starts_with(&*str1) => { step_2.iteratee = PStrIteratee::PStrSegment(f2, pstr2_atom, n2 + str1.len()); let c1_result = cycle_detection_step(i1, i2, &step_1); @@ -735,7 +735,7 @@ pub fn compare_pstr_prefixes<'a>( continue; } } - Ordering::Greater if str1.starts_with(str2) => { + Ordering::Greater if str1.starts_with(&*str2) => { step_1.iteratee = PStrIteratee::PStrSegment(f1, pstr1_atom, n1 + str2.len()); let c2_result = cycle_detection_step(i2, i1, &step_2); @@ -746,7 +746,7 @@ pub fn compare_pstr_prefixes<'a>( } } _ => { - return PStrCmpResult::Ordered(str1.cmp(str2)); + return PStrCmpResult::Ordered(str1.cmp(&*str2)); } } } @@ -808,7 +808,7 @@ mod test { let pstr_var_cell = put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[pstr_var_cell.get_value() as usize]; @@ -831,7 +831,7 @@ mod test { let pstr_second_var_cell = put_partial_string( &mut wam.machine_st.heap, "def", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_second_cell = wam.machine_st.heap[pstr_second_var_cell.get_value() as usize]; @@ -913,13 +913,21 @@ mod test { // construct a structurally similar but different cyclic partial string // matching the one beginning at wam.machine_st.heap[0]. - put_partial_string(&mut wam.machine_st.heap, "ab", &mut wam.machine_st.atom_tbl); + put_partial_string( + &mut wam.machine_st.heap, + "ab", + &mut wam.machine_st.atom_tbl.blocking_write(), + ); wam.machine_st.heap.pop(); wam.machine_st.heap.push(pstr_loc_as_cell!(second_h + 2)); - put_partial_string(&mut wam.machine_st.heap, "c ", &mut wam.machine_st.atom_tbl); + put_partial_string( + &mut wam.machine_st.heap, + "c ", + &mut wam.machine_st.atom_tbl.blocking_write(), + ); wam.machine_st.heap.pop(); @@ -947,7 +955,7 @@ mod test { put_partial_string( &mut wam.machine_st.heap, "abc ", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); let pstr_cell = wam.machine_st.heap[0]; @@ -981,7 +989,7 @@ mod test { let cstr_var_cell = put_complete_string( &mut wam.machine_st.heap, "abc", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); wam.machine_st.heap.push(list_loc_as_cell!(2)); @@ -1010,7 +1018,7 @@ mod test { let cstr_var_cell = put_complete_string( &mut wam.machine_st.heap, "abc", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); wam.machine_st.heap.push(list_loc_as_cell!(2)); @@ -1040,8 +1048,11 @@ mod test { wam.machine_st.heap.clear(); - let cstr_var_cell = - put_complete_string(&mut wam.machine_st.heap, "d", &mut wam.machine_st.atom_tbl); + let cstr_var_cell = put_complete_string( + &mut wam.machine_st.heap, + "d", + &mut wam.machine_st.atom_tbl.blocking_write(), + ); wam.machine_st.heap.push(list_loc_as_cell!(2)); wam.machine_st.heap.push(char_as_cell!('d')); @@ -1058,7 +1069,7 @@ mod test { let cstr_var_cell = put_complete_string( &mut wam.machine_st.heap, "abc", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); wam.machine_st.heap.push(list_loc_as_cell!(2)); @@ -1089,7 +1100,7 @@ mod test { put_complete_string( &mut wam.machine_st.heap, "abcdef", - &mut wam.machine_st.atom_tbl, + &mut wam.machine_st.atom_tbl.blocking_write(), ); wam.machine_st.heap.push(pstr_as_cell!(atom!("abc"))); diff --git a/src/machine/preprocessor.rs b/src/machine/preprocessor.rs index 3eba80af..f867ec70 100644 --- a/src/machine/preprocessor.rs +++ b/src/machine/preprocessor.rs @@ -313,11 +313,17 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>( } (atom!("module"), 2) => { let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl; - Ok(Declaration::Module(setup_module_decl(terms, atom_tbl)?)) + Ok(Declaration::Module(setup_module_decl( + terms, + &mut atom_tbl.blocking_write(), + )?)) } (atom!("op"), 3) => { let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl; - Ok(Declaration::Op(setup_op_decl(terms, atom_tbl)?)) + Ok(Declaration::Op(setup_op_decl( + terms, + &mut atom_tbl.blocking_write(), + )?)) } (atom!("non_counted_backtracking"), 1) => { let (name, arity) = setup_predicate_indicator(&mut terms.pop().unwrap())?; @@ -326,7 +332,8 @@ pub(super) fn setup_declaration<'a, LS: LoadState<'a>>( (atom!("use_module"), 1) => Ok(Declaration::UseModule(setup_use_module_decl(terms)?)), (atom!("use_module"), 2) => { let atom_tbl = &mut LS::machine_st(&mut loader.payload).atom_tbl; - let (name, exports) = setup_qualified_import(terms, atom_tbl)?; + let (name, exports) = + setup_qualified_import(terms, &mut atom_tbl.blocking_write())?; Ok(Declaration::UseQualifiedModule(name, exports)) } diff --git a/src/machine/streams.rs b/src/machine/streams.rs index 206e8263..b91ea8b8 100644 --- a/src/machine/streams.rs +++ b/src/machine/streams.rs @@ -1853,7 +1853,7 @@ impl MachineState { } }; - let file = match open_options.open(file_spec.as_str()) { + let file = match open_options.open(&*file_spec.as_str()) { Ok(file) => file, Err(err) => { match err.kind() { diff --git a/src/machine/system_calls.rs b/src/machine/system_calls.rs index d3c0cb44..561fdc07 100644 --- a/src/machine/system_calls.rs +++ b/src/machine/system_calls.rs @@ -1529,7 +1529,7 @@ impl Machine { } } (HeapCellValueTag::Char, c) => { - let name = self.machine_st.atom_tbl.build_with(&c.to_string()); + let name = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string()); let h = self.machine_st.heap.len(); self.machine_st.heap.push(atom_as_cell!(name)); @@ -1804,7 +1804,7 @@ impl Machine { match hostname::get().ok() { Some(host) => match host.to_str() { Some(host) => { - let hostname = self.machine_st.atom_tbl.build_with(host); + let hostname = self.machine_st.atom_tbl.blocking_write().build_with(host); let a1 = self.deref_register(1); self.machine_st.unify_atom(hostname, a1); @@ -1895,14 +1895,15 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - let path = std::path::Path::new(dir.as_str()); + let str = dir.as_str(); + let path = std::path::Path::new(&*str); let mut files = Vec::new(); if let Ok(entries) = fs::read_dir(path) { for entry in entries { if let Ok(entry) = entry { if let Some(name) = entry.file_name().to_str() { - let name = self.machine_st.atom_tbl.build_with(name); + let name = self.machine_st.atom_tbl.blocking_write().build_with(name); files.push(atom_as_cstr_cell!(name)); continue; @@ -1937,7 +1938,7 @@ impl Machine { .value_to_str_like(self.machine_st.registers[1]) { let len = Number::arena_from( - fs::metadata(file.as_str()).unwrap().len(), + fs::metadata(&*file.as_str()).unwrap().len(), &mut self.machine_st.arena, ); @@ -1963,8 +1964,8 @@ impl Machine { { let file_str = file.as_str(); - if !std::path::Path::new(file_str).exists() - || !fs::metadata(file_str).unwrap().is_file() + if !std::path::Path::new(&*file_str).exists() + || !fs::metadata(&*file_str).unwrap().is_file() { self.machine_st.fail = true; } @@ -1981,7 +1982,9 @@ impl Machine { { let dir_str = dir.as_str(); - if !std::path::Path::new(dir_str).exists() || !fs::metadata(dir_str).unwrap().is_dir() { + if !std::path::Path::new(&*dir_str).exists() + || !fs::metadata(&*dir_str).unwrap().is_dir() + { self.machine_st.fail = true; } } else { @@ -1997,7 +2000,7 @@ impl Machine { { let which = cell_as_atom!(self.deref_register(2)); - if let Ok(md) = fs::metadata(file.as_str()) { + if let Ok(md) = fs::metadata(&*file.as_str()) { if let Ok(time) = match which { atom!("modification") => md.modified(), atom!("access") => md.accessed(), @@ -2031,7 +2034,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - match fs::create_dir(dir.as_str()) { + match fs::create_dir(&*dir.as_str()) { Ok(_) => {} _ => { self.machine_st.fail = true; @@ -2048,7 +2051,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - match fs::create_dir_all(dir.as_str()) { + match fs::create_dir_all(&*dir.as_str()) { Ok(_) => {} _ => { self.machine_st.fail = true; @@ -2065,7 +2068,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - match fs::remove_file(file.as_str()) { + match fs::remove_file(&*file.as_str()) { Ok(_) => {} _ => { self.machine_st.fail = true; @@ -2084,7 +2087,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[2]) { - if fs::rename(file.as_str(), renamed.as_str()).is_ok() { + if fs::rename(&*file.as_str(), &*renamed.as_str()).is_ok() { return; } } @@ -2103,7 +2106,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[2]) { - if fs::copy(file.as_str(), copied.as_str()).is_ok() { + if fs::copy(&*file.as_str(), &*copied.as_str()).is_ok() { return; } } @@ -2118,7 +2121,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - match fs::remove_dir(dir.as_str()) { + match fs::remove_dir(&*dir.as_str()) { Ok(_) => {} _ => { self.machine_st.fail = true; @@ -2141,7 +2144,11 @@ impl Machine { } }; - let current_atom = self.machine_st.atom_tbl.build_with(¤t); + let current_atom = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(¤t); let a1 = self.deref_register(1); self.machine_st.unify_complete_string(current_atom, a1); @@ -2153,7 +2160,7 @@ impl Machine { let target = self.deref_register(2); if let Some(next) = self.machine_st.value_to_str_like(target) { - if env::set_current_dir(std::path::Path::new(next.as_str())).is_ok() { + if env::set_current_dir(std::path::Path::new(&*next.as_str())).is_ok() { return Ok(()); } } @@ -2169,7 +2176,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - match fs::canonicalize(path.as_str()) { + match fs::canonicalize(&*path.as_str()) { Ok(canonical) => { let cs = match canonical.to_str() { Some(s) => s, @@ -2182,7 +2189,7 @@ impl Machine { } }; - let canonical_atom = self.machine_st.atom_tbl.build_with(cs); + let canonical_atom = self.machine_st.atom_tbl.blocking_write().build_with(cs); let a2 = self.deref_register(2); self.machine_st.unify_complete_string(canonical_atom, a2); @@ -2241,13 +2248,13 @@ impl Machine { let atom_cell = match str_like { AtomOrString::Atom(atom) => { atom_as_cell!(if atom == atom!("[]") { - self.machine_st.atom_tbl.build_with("") + self.machine_st.atom_tbl.blocking_write().build_with("") } else { atom }) } AtomOrString::String(string) => { - atom_as_cell!(self.machine_st.atom_tbl.build_with(&string)) + atom_as_cell!(self.machine_st.atom_tbl.blocking_write().build_with(&string)) } }; @@ -2278,6 +2285,7 @@ impl Machine { } (HeapCellValueTag::Atom, (name, arity)) => { if arity == 0 { + let name = name.as_str(); let iter = name.chars() .map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64))); @@ -2292,6 +2300,7 @@ impl Machine { .get_name_and_arity(); if arity == 0 { + let name = name.as_str(); let iter = name.chars() .map(|c| fixnum_as_cell!(Fixnum::build_with(c as i64))); @@ -2307,7 +2316,7 @@ impl Machine { match self.machine_st.try_from_list(self.machine_st.registers[2], stub_gen) { Ok(addrs) => { let string = self.machine_st.codes_to_string(addrs.into_iter(), stub_gen)?; - let atom = self.machine_st.atom_tbl.build_with(&string); + let atom = self.machine_st.atom_tbl.blocking_write().build_with(&string); self.machine_st.bind(a1.as_var().unwrap(), atom_as_cell!(atom)); } @@ -2334,7 +2343,7 @@ impl Machine { .get_name_and_arity(); if arity == 0 { - name.chars().count() as i64 + name.as_str().chars().count() as i64 } else { self.machine_st.fail = true; return; @@ -2342,7 +2351,7 @@ impl Machine { } (HeapCellValueTag::Atom, (name, arity)) => { if arity == 0 { - name.chars().count() as i64 + name.as_str().chars().count() as i64 } else { self.machine_st.fail = true; return; @@ -2392,7 +2401,7 @@ impl Machine { let atom_or_string = self.machine_st.value_to_str_like(a1).unwrap(); self.machine_st - .parse_number_from_string(atom_or_string.as_str(), &self.indices, stub_gen) + .parse_number_from_string(&*atom_or_string.as_str(), &self.indices, stub_gen) } #[inline(always)] @@ -2801,7 +2810,11 @@ impl Machine { } }; - let chars_atom = self.machine_st.atom_tbl.build_with(&string.trim()); + let chars_atom = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(&string.trim()); self.machine_st.unify_complete_string(chars_atom, chs); } @@ -3027,14 +3040,14 @@ impl Machine { match (name, arity) { (atom!("to_upper"), 1) => { let reg = self.machine_st.deref(self.machine_st.heap[s+1]); - let atom = self.machine_st.atom_tbl.build_with(&c.to_uppercase().to_string()); + let atom = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_uppercase().to_string()); let upper_str = string_as_cstr_cell!(atom); unify!(self.machine_st, reg, upper_str); self.machine_st.fail = false; } (atom!("to_lower"), 1) => { let reg = self.machine_st.deref(self.machine_st.heap[s+1]); - let atom = self.machine_st.atom_tbl.build_with(&c.to_lowercase().to_string()); + let atom = self.machine_st.atom_tbl.blocking_write().build_with(&c.to_lowercase().to_string()); let lower_str = string_as_cstr_cell!(atom); unify!(self.machine_st, reg, lower_str); self.machine_st.fail = false; @@ -3557,7 +3570,11 @@ impl Machine { }; let output = self.deref_register(3); - let atom = self.machine_st.atom_tbl.build_with(&string); + let atom = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(&string); self.machine_st.unify_complete_string(atom, output); Ok(()) @@ -4052,7 +4069,7 @@ impl Machine { cell_as_atom!(self.machine_st.heap[s]) } (HeapCellValueTag::Char, c) => { - self.machine_st.atom_tbl.build_with(&c.to_string()) + self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string()) } _ => { unreachable!() @@ -4374,7 +4391,7 @@ impl Machine { (HeapCellValueTag::Str, s) => { let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name(); let value = self.machine_st.value_to_str_like(self.machine_st.heap[s + 1]).unwrap(); - header_map.insert(HeaderName::from_str(name.as_str()).unwrap(), HeaderValue::from_str(value.as_str()).unwrap()); + header_map.insert(HeaderName::from_str(&*name.as_str()).unwrap(), HeaderValue::from_str(&*value.as_str()).unwrap()); } _ => { unreachable!() @@ -4414,10 +4431,14 @@ impl Machine { let h = self.machine_st.heap.len(); let header_term = functor!( - self.machine_st.atom_tbl.build_with(header_name.as_str()), + self.machine_st + .atom_tbl + .blocking_write() + .build_with(header_name.as_str()), [cell(string_as_cstr_cell!(self .machine_st .atom_tbl + .blocking_write() .build_with(header_value.to_str().unwrap())))] ); @@ -4437,7 +4458,10 @@ impl Machine { let reader = resp.bytes().unwrap().reader(); let mut stream = Stream::from_http_stream( - self.machine_st.atom_tbl.build_with(&address_string), + self.machine_st + .atom_tbl + .blocking_write() + .build_with(&address_string), Box::new(reader), &mut self.machine_st.arena, ); @@ -4554,14 +4578,14 @@ impl Machine { Method::HEAD => atom!("head"), _ => unreachable!(), }; - let path_atom = self.machine_st.atom_tbl.build_with(request.request.uri().path()); + let path_atom = self.machine_st.atom_tbl.blocking_write().build_with(request.request.uri().path()); let path_cell = atom_as_cstr_cell!(path_atom); let headers: Vec = request.request.headers().iter().map(|(header_name, header_value)| { let h = self.machine_st.heap.len(); let header_term = functor!( - self.machine_st.atom_tbl.build_with(header_name.as_str()), - [cell(string_as_cstr_cell!(self.machine_st.atom_tbl.build_with(header_value.to_str().unwrap())))] + self.machine_st.atom_tbl.blocking_write().build_with(header_name.as_str()), + [cell(string_as_cstr_cell!(self.machine_st.atom_tbl.blocking_write().build_with(header_value.to_str().unwrap())))] ); self.machine_st.heap.extend(header_term.into_iter()); @@ -4571,7 +4595,7 @@ impl Machine { let headers_list = iter_to_heap_list(&mut self.machine_st.heap, headers.into_iter()); let query_str = request.request.uri().query().unwrap_or(""); - let query_atom = self.machine_st.atom_tbl.build_with(query_str); + let query_atom = self.machine_st.atom_tbl.blocking_write().build_with(query_str); let query_cell = string_as_cstr_cell!(query_atom); let hyper_req = request.request; @@ -4642,7 +4666,7 @@ impl Machine { (HeapCellValueTag::Str, s) => { let name = cell_as_atom_cell!(self.machine_st.heap[s]).get_name(); let value = self.machine_st.value_to_str_like(self.machine_st.heap[s + 1]).unwrap(); - header_map.insert(HeaderName::from_str(name.as_str()).unwrap(), HeaderValue::from_str(value.as_str()).unwrap()); + header_map.insert(HeaderName::from_str(&*name.as_str()).unwrap(), HeaderValue::from_str(&*value.as_str()).unwrap()); } _ => { unreachable!() @@ -4722,7 +4746,7 @@ impl Machine { } if let Ok(_) = self .foreign_function_table - .load_library(library_name.as_str(), &functions) + .load_library(&*library_name.as_str(), &functions) { return Ok(()); } @@ -4752,7 +4776,7 @@ impl Machine { _ => { let stub_gen = || functor_stub(atom!("foreign_call"), 3); if let Some(string) = machine_st.value_to_str_like(source) { - Value::CString(CString::new(string.as_str()).unwrap()) + Value::CString(CString::new(&*string.as_str()).unwrap()) } else { match machine_st.try_from_list(source, stub_gen) { Ok(args) => { @@ -4785,7 +4809,7 @@ impl Machine { .collect(); match self .foreign_function_table - .exec(function_name.as_str(), args) + .exec(&*function_name.as_str(), args) { Ok(result) => { match result { @@ -4801,8 +4825,11 @@ impl Machine { unify!(self.machine_st, return_value, struct_value); } Value::CString(cstr) => { - let cstr = - self.machine_st.atom_tbl.build_with(cstr.to_str().unwrap()); + let cstr = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(cstr.to_str().unwrap()); self.machine_st.unify_complete_string(cstr, return_value); } } @@ -4834,6 +4861,7 @@ impl Machine { Value::CString(cstr) => atom_as_cell!(self .machine_st .atom_tbl + .blocking_write() .build_with(&cstr.into_string().unwrap())), Value::Struct(name, struct_args) => self.build_struct(&name, struct_args), }) @@ -4863,7 +4891,7 @@ impl Machine { Err(e) => return Err(e), }; self.foreign_function_table - .define_struct(struct_name.as_str(), fields); + .define_struct(&*struct_name.as_str(), fields); return Ok(()); } self.machine_st.fail = true; @@ -4890,7 +4918,7 @@ impl Machine { let src_sink = self.deref_register(1); if let Some(file_spec) = self.machine_st.value_to_str_like(src_sink) { - let file_spec = file_spec.as_atom(&mut self.machine_st.atom_tbl); + let file_spec = file_spec.as_atom(&mut self.machine_st.atom_tbl.blocking_write()); let mut stream = self.machine_st @@ -4933,7 +4961,7 @@ impl Machine { let op = read_heap_cell!(self.deref_register(3), (HeapCellValueTag::Char, c) => { - self.machine_st.atom_tbl.build_with(&c.to_string()) + self.machine_st.atom_tbl.blocking_write().build_with(&c.to_string()) } (HeapCellValueTag::Atom, (name, _arity)) => { name @@ -6103,7 +6131,7 @@ impl Machine { write_term_to_heap( &term, &mut self.machine_st.heap, - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ) }); @@ -6268,7 +6296,7 @@ impl Machine { name } _ => { - self.machine_st.atom_tbl.build_with(&match Number::try_from(port) { + self.machine_st.atom_tbl.blocking_write().build_with(&match Number::try_from(port) { Ok(Number::Fixnum(n)) => n.get_num().to_string(), Ok(Number::Integer(n)) => n.to_string(), _ => { @@ -6282,7 +6310,10 @@ impl Machine { atom!("127.0.0.1:80") } else { let buffer = format!("{}:{}", socket_atom.as_str(), port.as_str()); - self.machine_st.atom_tbl.build_with(&buffer) + self.machine_st + .atom_tbl + .blocking_write() + .build_with(&buffer) }; let alias = self.machine_st.registers[4]; @@ -6310,7 +6341,7 @@ impl Machine { } } - let stream = match TcpStream::connect(socket_addr.as_str()).map_err(|e| e.kind()) { + let stream = match TcpStream::connect(&*socket_addr.as_str()).map_err(|e| e.kind()) { Ok(tcp_stream) => { let mut stream = Stream::from_tcp_stream(socket_addr, tcp_stream, &mut self.machine_st.arena); @@ -6464,7 +6495,7 @@ impl Machine { (ArenaHeaderTag::TcpListener, tcp_listener) => { match tcp_listener.accept().ok() { Some((tcp_stream, socket_addr)) => { - let client = self.machine_st.atom_tbl.build_with(&socket_addr.to_string()); + let client = self.machine_st.atom_tbl.blocking_write().build_with(&socket_addr.to_string()); let mut tcp_stream = Stream::from_tcp_stream( client, @@ -6520,7 +6551,7 @@ impl Machine { )?; let connector = TlsConnector::new().unwrap(); - let stream = match connector.connect(hostname.as_str(), stream0) { + let stream = match connector.connect(&*hostname.as_str(), stream0) { Ok(tls_stream) => tls_stream, Err(_) => { return Err(self.machine_st.open_permission_error( @@ -6555,7 +6586,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[2]) { - let identity = match Identity::from_pkcs12(&pkcs12, password.as_str()) { + let identity = match Identity::from_pkcs12(&pkcs12, &*password.as_str()) { Ok(identity) => identity, Err(_) => { return Err(self.machine_st.open_permission_error( @@ -7088,7 +7119,7 @@ impl Machine { let chars = put_complete_string( &mut self.machine_st.heap, &result, - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ); let result_addr = self.deref_register(1); @@ -7107,7 +7138,7 @@ impl Machine { use git_version::git_version; let buffer = git_version!(cargo_prefix = "cargo:", fallback = "unknown"); - let buffer_atom = self.machine_st.atom_tbl.build_with(buffer); + let buffer_atom = self.machine_st.atom_tbl.blocking_write().build_with(buffer); let a1 = self.deref_register(1); self.machine_st.unify_complete_string(buffer_atom, a1); @@ -7472,7 +7503,11 @@ impl Machine { if buffer.len() == 0 { empty_list_as_cell!() } else { - atom_as_cstr_cell!(self.machine_st.atom_tbl.build_with(&buffer)) + atom_as_cstr_cell!(self + .machine_st + .atom_tbl + .blocking_write() + .build_with(&buffer)) } }; @@ -7609,7 +7644,11 @@ impl Machine { if let Some(string) = self.machine_st.value_to_str_like(addr) { for c in string.as_str().chars() { if c as u32 > 255 { - let non_octet = self.machine_st.atom_tbl.build_with(&c.to_string()); + let non_octet = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(&c.to_string()); self.machine_st .unify_atom(non_octet, self.machine_st.registers[2]); return; @@ -7641,7 +7680,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - match roxmltree::Document::parse(string.as_str()) { + match roxmltree::Document::parse(&*string.as_str()) { Ok(doc) => { let result = self.xml_node_to_term(doc.root_element()); unify!(self.machine_st, self.machine_st.registers[2], result); @@ -7661,12 +7700,12 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) { - match env::var(key.as_str()) { + match env::var(&*key.as_str()) { Ok(value) => { let cstr = put_complete_string( &mut self.machine_st.heap, &value, - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ); unify!(self.machine_st, self.machine_st.registers[2], cstr); @@ -7691,7 +7730,7 @@ impl Machine { .value_to_str_like(self.machine_st.registers[2]) .unwrap(); - env::set_var(key.as_str(), value.as_str()); + env::set_var(&*key.as_str(), &*value.as_str()); } #[inline(always)] @@ -7700,7 +7739,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[1]) .unwrap(); - env::remove_var(key.as_str()); + env::remove_var(&*key.as_str()); } #[inline(always)] @@ -7756,7 +7795,7 @@ impl Machine { Ok(value) => { let command = process::Command::new(&value) .arg("-c") - .arg(command.as_str()) + .arg(&*command.as_str()) .status(); command_result(&mut self.machine_st, command); } @@ -7764,7 +7803,7 @@ impl Machine { Ok(value) => { let command = process::Command::new(&value) .arg("/C") - .arg(command.as_str()) + .arg(&*command.as_str()) .status(); command_result(&mut self.machine_st, command); } @@ -7799,7 +7838,7 @@ impl Machine { .machine_st .value_to_str_like(self.machine_st.registers[2]) .unwrap(); - let bytes = base64::decode_config(b64.as_str(), config); + let bytes = base64::decode_config(&*b64.as_str(), config); match bytes { Ok(bs) => { @@ -7839,7 +7878,7 @@ impl Machine { use crate::machine::LIBRARIES; - match LIBRARIES.borrow().get(library_name.as_str()) { + match LIBRARIES.borrow().get(&*library_name.as_str()) { Some(library) => { let lib_stream = Stream::from_static_string(library, &mut self.machine_st.arena); unify!( @@ -7851,10 +7890,14 @@ impl Machine { let mut path_buf = machine::current_dir(); path_buf.push("/lib"); - path_buf.push(library_name.as_str()); + path_buf.push(&*library_name.as_str()); let library_path_str = path_buf.to_str().unwrap(); - let library_path = self.machine_st.atom_tbl.build_with(library_path_str); + let library_path = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(library_path_str); self.machine_st .unify_atom(library_path, self.machine_st.registers[3]); @@ -7954,7 +7997,7 @@ impl Machine { let path_string = put_complete_string( &mut self.machine_st.heap, path, - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ); unify!(self.machine_st, self.machine_st.registers[1], path_string); @@ -8001,7 +8044,7 @@ impl Machine { fstr.push_str("finis]."); let s = datetime.format(&fstr).to_string(); - self.machine_st.atom_tbl.build_with(&s) + self.machine_st.atom_tbl.blocking_write().build_with(&s) } pub(super) fn string_encoding_bytes( @@ -8025,17 +8068,21 @@ impl Machine { put_complete_string( &mut self.machine_st.heap, node.text().unwrap(), - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ) } else { let mut avec = Vec::new(); for attr in node.attributes() { - let name = self.machine_st.atom_tbl.build_with(attr.name()); + let name = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(attr.name()); let value = put_complete_string( &mut self.machine_st.heap, &attr.value(), - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ); avec.push(str_loc_as_cell!(self.machine_st.heap.len())); @@ -8061,7 +8108,11 @@ impl Machine { cvec.into_iter() )); - let tag = self.machine_st.atom_tbl.build_with(node.tag_name().name()); + let tag = self + .machine_st + .atom_tbl + .blocking_write() + .build_with(node.tag_name().name()); let result = str_loc_as_cell!(self.machine_st.heap.len()); @@ -8081,17 +8132,17 @@ impl Machine { None => put_complete_string( &mut self.machine_st.heap, &node.text(), - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ), Some(name) => { let mut avec = Vec::new(); for attr in node.attrs() { - let name = self.machine_st.atom_tbl.build_with(attr.0); + let name = self.machine_st.atom_tbl.blocking_write().build_with(attr.0); let value = put_complete_string( &mut self.machine_st.heap, &attr.1, - &mut self.machine_st.atom_tbl, + &mut self.machine_st.atom_tbl.blocking_write(), ); avec.push(str_loc_as_cell!(self.machine_st.heap.len())); @@ -8117,7 +8168,7 @@ impl Machine { cvec.into_iter() )); - let tag = self.machine_st.atom_tbl.build_with(name); + let tag = self.machine_st.atom_tbl.blocking_write().build_with(name); let result = str_loc_as_cell!(self.machine_st.heap.len()); self.machine_st @@ -8138,7 +8189,11 @@ impl Machine { if buffer.len() == 0 { empty_list_as_cell!() } else { - atom_as_cstr_cell!(self.machine_st.atom_tbl.build_with(&buffer)) + atom_as_cstr_cell!(self + .machine_st + .atom_tbl + .blocking_write() + .build_with(&buffer)) } } } diff --git a/src/parser/lexer.rs b/src/parser/lexer.rs index 793fe701..dde0f03d 100644 --- a/src/parser/lexer.rs +++ b/src/parser/lexer.rs @@ -638,7 +638,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { Ok(Token::Literal(Literal::Atom(atom!("[]")))) } else { Ok(Token::Literal(Literal::Atom( - self.machine_st.atom_tbl.build_with(&token), + self.machine_st.atom_tbl.blocking_write().build_with(&token), ))) } } @@ -1083,7 +1083,7 @@ impl<'a, R: CharRead> Lexer<'a, R> { if c == '"' { let s = self.char_code_list_token(c)?; - let atom = self.machine_st.atom_tbl.build_with(&s); + let atom = self.machine_st.atom_tbl.blocking_write().build_with(&s); return if let DoubleQuotes::Atom = self.machine_st.flags.double_quotes { Ok(Token::Literal(Literal::Atom(atom))) diff --git a/src/parser/parser.rs b/src/parser/parser.rs index dd86640c..d1ba7941 100644 --- a/src/parser/parser.rs +++ b/src/parser/parser.rs @@ -107,7 +107,7 @@ pub(crate) fn as_partial_string( tail_ref = tail; } Term::CompleteString(_, cstr) => { - string += cstr.as_str(); + string += &*cstr.as_str(); tail = Term::Literal(Cell::default(), Literal::Atom(atom!("[]"))); break; } @@ -122,7 +122,7 @@ pub(crate) fn as_partial_string( Term::AnonVar | Term::Var(..) => Ok((string, Some(Box::new(tail)))), Term::Literal(_, Literal::Atom(atom!("[]"))) => Ok((string, None)), Term::Literal(_, Literal::String(tail)) => { - string += tail.as_str(); + string += &*tail.as_str(); Ok((string, None)) } _ => Ok((string, Some(Box::new(tail)))), @@ -568,16 +568,19 @@ impl<'a, R: CharRead> Parser<'a, R> { let idx = self.terms.len() - arity; if TokenType::Term == self.stack[stack_len].tt { - if atomize_term(&mut self.lexer.machine_st.atom_tbl, &self.terms[idx - 1]).is_some() { + if atomize_term( + &mut self.lexer.machine_st.atom_tbl.blocking_write(), + &self.terms[idx - 1], + ) + .is_some() + { self.stack.truncate(stack_len + 1); let mut subterms: Vec<_> = self.terms.drain(idx..).collect(); - if let Some(name) = self - .terms - .pop() - .and_then(|t| atomize_term(&mut self.lexer.machine_st.atom_tbl, &t)) - { + if let Some(name) = self.terms.pop().and_then(|t| { + atomize_term(&mut self.lexer.machine_st.atom_tbl.blocking_write(), &t) + }) { // reduce the '.' functor to a cons cell if it applies. if name == atom!(".") && subterms.len() == 2 { let tail = subterms.pop().unwrap(); @@ -588,7 +591,12 @@ impl<'a, R: CharRead> Parser<'a, R> { Term::PartialString(Cell::default(), string_buf, tail) } Ok((string_buf, None)) => { - let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf); + let atom = self + .lexer + .machine_st + .atom_tbl + .blocking_write() + .build_with(&string_buf); Term::CompleteString(Cell::default(), atom) } Err(term) => term, @@ -755,7 +763,12 @@ impl<'a, R: CharRead> Parser<'a, R> { Term::PartialString(Cell::default(), string_buf, tail) } Ok((string_buf, None)) => { - let atom = self.lexer.machine_st.atom_tbl.build_with(&string_buf); + let atom = self + .lexer + .machine_st + .atom_tbl + .blocking_write() + .build_with(&string_buf); Term::CompleteString(Cell::default(), atom) } Err(term) => term, @@ -971,7 +984,9 @@ impl<'a, R: CharRead> Parser<'a, R> { |n, arena| Literal::from(float_alloc!(n, arena)), ), Token::Literal(c) => { - if let Some(name) = atomize_constant(&mut self.lexer.machine_st.atom_tbl, c) { + let atomized = + atomize_constant(&mut self.lexer.machine_st.atom_tbl.blocking_write(), c); + if let Some(name) = atomized { if !self.shift_op(name, op_dir)? { self.shift(Token::Literal(c), 0, TERM); } diff --git a/src/read.rs b/src/read.rs index abfbb395..b5ed91bc 100644 --- a/src/read.rs +++ b/src/read.rs @@ -16,7 +16,9 @@ use crate::types::*; use fxhash::FxBuildHasher; -use indexmap::IndexSet; +use tokio::sync::RwLock; + +use std::sync::Arc; #[cfg(feature = "repl")] use rustyline::error::ReadlineError; @@ -79,7 +81,7 @@ impl MachineState { }; inner.add_lines_read(num_lines_read); - write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl) + write_term_to_heap(&term, &mut self.heap, &mut self.atom_tbl.blocking_write()) } } @@ -112,48 +114,48 @@ pub struct ReadlineStream { } impl ReadlineStream { - #[cfg(feature = "repl")] #[inline] pub fn new(pending_input: &str, add_history: bool) -> Self { - let config = Config::builder().check_cursor_position(true).build(); + #[cfg(feature = "repl")] + { + let config = Config::builder().check_cursor_position(true).build(); - let helper = Helper::new(); + let helper = Helper::new(); - let mut rl = Editor::with_config(config).unwrap(); - rl.set_helper(Some(helper)); + let mut rl = Editor::with_config(config).unwrap(); + rl.set_helper(Some(helper)); - if let Some(mut path) = dirs_next::home_dir() { - path.push(HISTORY_FILE); - if path.exists() && rl.load_history(&path).is_err() { - println!("Warning: loading history failed"); + if let Some(mut path) = dirs_next::home_dir() { + path.push(HISTORY_FILE); + if path.exists() && rl.load_history(&path).is_err() { + println!("Warning: loading history failed"); + } } - } - ReadlineStream { - rl, - pending_input: CharReader::new(Cursor::new(pending_input.to_owned())), - add_history: add_history, + ReadlineStream { + rl, + pending_input: CharReader::new(Cursor::new(pending_input.to_owned())), + add_history: add_history, + } } - } - #[cfg(not(feature = "repl"))] - #[inline] - pub fn new(pending_input: &str, add_history: bool) -> Self { - ReadlineStream { - pending_input: CharReader::new(Cursor::new(pending_input.to_owned())), - add_history: add_history, + #[cfg(not(feature = "repl"))] + { + ReadlineStream { + pending_input: CharReader::new(Cursor::new(pending_input.to_owned())), + add_history: add_history, + } } } - #[cfg(feature = "repl")] - pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet) { - let helper = self.rl.helper_mut().unwrap(); - helper.atoms = atoms; + pub fn set_atoms_for_completion(&mut self, atoms: &Arc>) { + #[cfg(feature = "repl")] + { + let helper = self.rl.helper_mut().unwrap(); + helper.atoms = Arc::downgrade(atoms); + } } - #[cfg(not(feature = "repl"))] - pub fn set_atoms_for_completion(&mut self, atoms: *const IndexSet) {} - #[inline] pub fn reset(&mut self) { self.pending_input.reset_buffer(); @@ -433,7 +435,7 @@ impl<'a, 'b> TermWriter<'a, 'b> { continue; } &TermRef::CompleteString(_, _, ref src) => { - put_complete_string(self.heap, src.as_str(), self.atom_tbl); + put_complete_string(self.heap, &src.as_str(), self.atom_tbl); } &TermRef::PartialString(lvl, _, ref src, _) => { if let Level::Root = lvl { diff --git a/src/repl_helper.rs b/src/repl_helper.rs index 4edf2729..a61d711a 100644 --- a/src/repl_helper.rs +++ b/src/repl_helper.rs @@ -1,23 +1,26 @@ -use indexmap::IndexSet; -use rustyline::completion::{Candidate, Completer}; +use rustyline::completion::Completer; use rustyline::highlight::{Highlighter, MatchingBracketHighlighter}; use rustyline::hint::Hinter; use rustyline::validate::Validator; use rustyline::{Context, Helper as RlHelper, Result}; -use crate::atom_table::{Atom, STATIC_ATOMS_MAP}; +use tokio::sync::RwLock; + +use std::sync::Weak; + +use crate::atom_table::{AtomString, AtomTable, STATIC_ATOMS_MAP}; // TODO: Maybe add validation to the helper pub struct Helper { highligher: MatchingBracketHighlighter, - pub atoms: *const IndexSet, + pub atoms: Weak>, } impl Helper { pub fn new() -> Self { Self { highligher: MatchingBracketHighlighter::new(), - atoms: std::ptr::null(), + atoms: Weak::new(), } } } @@ -54,20 +57,8 @@ fn get_prefix(line: &str, pos: usize) -> Option { start_of_atom } -pub struct StrPtr(*const str); - -impl Candidate for StrPtr { - fn display(&self) -> &str { - unsafe { self.0.as_ref().unwrap() } - } - - fn replacement(&self) -> &str { - unsafe { self.0.as_ref().unwrap() } - } -} - impl Completer for Helper { - type Candidate = StrPtr; + type Candidate = AtomString<'static>; fn complete( &self, @@ -78,17 +69,21 @@ impl Completer for Helper { let start_of_prefix = get_prefix(line, pos); if let Some(idx) = start_of_prefix { let sub_str = line.get(idx..pos).unwrap(); - Ok((idx, unsafe { - let mut matching = (*self.atoms) - .iter() - .chain(STATIC_ATOMS_MAP.values()) - .filter(|a| a.as_str().starts_with(sub_str)) - .map(|s| StrPtr(s.as_str())) - .collect::>(); - - matching.sort_unstable_by(|a, b| Ord::cmp(&(*a.0).len(), &(*b.0).len())); - matching - })) + + let guard = tokio::runtime::Handle::current() + .block_on(self.atoms.upgrade().unwrap().read_owned()); + + let mut matching = guard + .table + .iter() + .chain(STATIC_ATOMS_MAP.values()) + .map(|a| a.as_str()) + .filter(|a| a.starts_with(sub_str)) + .collect::>(); + + matching.sort_unstable_by(|a, b| Ord::cmp(&a.len(), &b.len())); + + Ok((idx, matching)) } else { Ok((0, vec![])) }