]> Repositorios git - scryer-prolog.git/commitdiff
[WIP] make AtomTable concurrentcy ready
authorSkgland <[email protected]>
Fri, 25 Aug 2023 23:10:49 +0000 (01:10 +0200)
committerBennet Bleßmann <[email protected]>
Tue, 5 Sep 2023 17:12:22 +0000 (19:12 +0200)
25 files changed:
Cargo.toml
src/arena.rs
src/atom_table.rs
src/codegen.rs
src/ffi.rs
src/forms.rs
src/heap_iter.rs
src/heap_print.rs
src/machine/compile.rs
src/machine/copier.rs
src/machine/gc.rs
src/machine/load_state.rs
src/machine/loader.rs
src/machine/machine_state.rs
src/machine/machine_state_impl.rs
src/machine/mock_wam.rs
src/machine/mod.rs
src/machine/partial_string.rs
src/machine/preprocessor.rs
src/machine/streams.rs
src/machine/system_calls.rs
src/parser/lexer.rs
src/parser/parser.rs
src/read.rs
src/repl_helper.rs

index 94f589d042776d4117d9ac345343e09b591691d5..d38c6355d7a35d2e21c580379198e9b17e977cf5 100644 (file)
@@ -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"
index c58db7a595fe8e28e23a7fab4a74ab8085c48484..0ecec6508e33570190c16dd8b1c2a1f892c82904 100644 (file)
@@ -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!() }
         );
index f3b91a583f51405dcc8202e50f26d3d7c9ce2240..704bc5235a1d127a3078b6cdca070b065480d85a 100644 (file)
@@ -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<bool> 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<Atom> for str {
+    fn equivalent(&self, atom: &Atom) -> bool {
+        &*atom.as_str() == self
+    }
 }
 
-#[cfg(not(test))]
-static ATOM_TABLE_BUF_BASE: std::sync::atomic::AtomicPtr<u8> =
-    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<Weak<RwLock<AtomTable>>> {
+    #[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<Weak<RwLock<AtomTable>>> = 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<RwLock<Weak<RwLock<AtomTable>>>> = 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<str> for Atom {
-    #[inline]
-    fn borrow(&self) -> &str {
-        self.as_str()
-    }
-}
-
 impl Hash for Atom {
     #[inline]
     fn hash<H: Hasher>(&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<AtomTable, str>),
+}
+
+impl AtomString<'_> {
+    pub fn map<F>(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::<AtomHeader>()) 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<OwnedRwLockReadGuard<AtomTable, u8>> {
+        if let Some(guard) = self.as_ptr() {
+            Some(OwnedRwLockReadGuard::map(guard, |ptr| unsafe {
+                (ptr as *const u8)
+                    .offset(mem::size_of::<AtomHeader>() 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<OwnedRwLockReadGuard<AtomTable, u8>> {
         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::<AtomHeader>(ptr as *const _);
-            let len = header.len() as usize;
-            let buf = (ptr as usize + mem::size_of::<AtomHeader>()) 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::<AtomHeader>(ptr as *const u8 as *const AtomHeader) };
+                let len = header.len() as usize;
+                let buf =
+                    (unsafe { (ptr as *const u8).offset(mem::size_of::<AtomHeader>() 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<Atom>,
 }
 
-#[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<RwLock<Self>> {
+        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::<AtomHeader>();
             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)]
index 685077ba94090e538673214f40a0cf04e06d86a0..ca4e26049732dc4fd279272f41a87bbbd4f1549c 100644 (file)
@@ -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<AtomTable>,
     marker: DebrayAllocator,
     settings: CodeGenSettings,
     pub(crate) skeleton: PredicateSkeleton,
@@ -362,7 +364,7 @@ fn structure_cell(term: &Term) -> Option<&Cell<RegType>> {
 }
 
 impl<'b> CodeGenerator<'b> {
-    pub(crate) fn new(atom_tbl: &'b mut AtomTable, settings: CodeGenSettings) -> Self {
+    pub(crate) fn new(atom_tbl: &'b RwLock<AtomTable>, 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::<Target>(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::<Target>(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(),
+                    );
                 }
             }
 
index d8553315cccc2e12339b7b8d8889ff9342ebde7e..8fd55dbcc05534114fcb31fac4363ceebe5b8f4a 100644 (file)
@@ -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);
                     }
index 0912fbe9950529c281d1534e344f847cd6202b57..54e5dd45cd74a6536c7f93c2ffca398acf505859 100644 (file)
@@ -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()),
         }
     }
 
index caf72439e7b7b7312c6786c92e2f28e77763b9c6..e1a2d0a1435658eb64caeb9e3205f8da6fd64540 100644 (file)
@@ -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];
index 759cf1ed1bdaeb446ee9eb1abb369b88cbc10f99..8cd175fab5bcfe5a8ead219ffbf589389a84340f 100644 (file)
@@ -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<RwLock<AtomTable>>,
     op_dir: &'a OpDir,
     state_stack: Vec<TokenOrRedirect>,
     toplevel_spec: Option<DirectedOp>,
@@ -549,7 +552,7 @@ pub(crate) fn numbervar(offset: &Integer, addr: HeapCellValue) -> Option<String>
 impl<'a, Outputter: HCValueOutputter> HCPrinter<'a, Outputter> {
     pub fn new(
         heap: &'a mut Heap,
-        atom_tbl: &'a mut AtomTable,
+        atom_tbl: Arc<RwLock<AtomTable>>,
         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(),
index 2c6ee8086f948392245d87aec3d5a7366666f0e3..c8bf345160376c7f549b71eba1ef55c5f3675efd 100644 (file)
@@ -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)?;
 
index 093cb735ecfe59ca82df9ccd62a3f10858de438a..6b15298fb4b7909ca772323ed924d5e39897e2be 100644 (file)
@@ -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];
 
index eb5d86df21b0d09d8b093d9b210db824cea9769f..2160fc5970bcddc3cb65a23037515bb3774b16ac 100644 (file)
@@ -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];
 
index 92cca6600c64d9a3b3afb4eb388a82e614fa000a..fd857f3d89622bd499321a7308f4c998a9bb4fd1 100644 (file)
@@ -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);
index c42610a525bd3808261290ab5acae236ef2de309..d42f923c69b7686d7d32bab41e776ab631333803 100644 (file)
@@ -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]);
index 4e344844eaab7d12d6df2e18804d2c5b17ea6c64..c5ae21a4eb26cb77e825737a165bd39f1aa52233 100644 (file)
@@ -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<RwLock<AtomTable>>,
     pub arena: Arena,
     pub(super) pdl: Vec<HeapCellValue>,
     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<Atom>;
-
         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(),
index 964e30bb3474eaaa0fea476169b0339ec59bc635..991cccfa5c1733b2f1a1838bbce8d8032b58c83c 100644 (file)
@@ -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,
index 69b04139ba77a403489377a0e8ada22ae7f38097..7be95fbd0f4c18cc74c3f96a76e4429dcca037db 100644 (file)
@@ -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(),
index 009a9ba5f461a11520426e7dd843bb1a3189995b..d67fc861cb026115d743fbf90a18071a19336418 100644 (file)
@@ -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(),
             ));
         }
 
index 3cdd03ec0336fe7c880909fb0528e0eb493ffac8..5605474dfe14ea6bd7fa4bff225fc3d42c20db4a 100644 (file)
@@ -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")));
index 3eba80af1f30261c091a4826293deffc82895a2f..f867ec7093cb484081ba4a23dfb4f744a4fce0d5 100644 (file)
@@ -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))
             }
index 206e82632ad3d89ecfa0a94eb05bfe194abf97b5..b91ea8b855458191e7a772515c9f780c73c56fec 100644 (file)
@@ -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() {
index d3c0cb445d4ac1c30d050336d14e2bfb54ce2e17..561fdc074f034cf0891f86428352bf595d5bb033 100644 (file)
@@ -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(&current);
+            let current_atom = self
+                .machine_st
+                .atom_tbl
+                .blocking_write()
+                .build_with(&current);
 
             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<HeapCellValue> = 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))
         }
     }
 }
index 793fe701d19ef9662ed4ec3025c5d073f5e238ae..dde0f03d59beaa13866bad167592b9e1612a48ba 100644 (file)
@@ -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)))
index dd86640c90cb62fa2dd146f4adaa1195705f473e..d1ba7941c978984701d667742ac559c869e2908d 100644 (file)
@@ -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);
                     }
index abfbb3958e7f3750f667ed9a8164e096059a35b7..b5ed91bc919ab77b6d8ae7d9bd9c611892cb95f7 100644 (file)
@@ -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<Atom>) {
-        let helper = self.rl.helper_mut().unwrap();
-        helper.atoms = atoms;
+    pub fn set_atoms_for_completion(&mut self, atoms: &Arc<RwLock<AtomTable>>) {
+        #[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<Atom>) {}
-
     #[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 {
index 4edf2729297330792feb9ee94689cd7c689f70f8..a61d711a4d689a45b074a68fc876ca64c4e3ab78 100644 (file)
@@ -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<Atom>,
+    pub atoms: Weak<RwLock<AtomTable>>,
 }
 
 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<usize> {
     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::<Vec<_>>();
-
-                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::<Vec<_>>();
+
+            matching.sort_unstable_by(|a, b| Ord::cmp(&a.len(), &b.len()));
+
+            Ok((idx, matching))
         } else {
             Ok((0, vec![]))
         }