diff --git a/Cargo.lock b/Cargo.lock index 7eba77637..78ac90b39 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -429,6 +429,7 @@ version = "0.7.1" dependencies = [ "atty", "itertools 0.11.0", + "lazy_static", "petgraph", "serde", "serde_json", diff --git a/calyx-utils/Cargo.toml b/calyx-utils/Cargo.toml index da438c0d4..6d3dc9469 100644 --- a/calyx-utils/Cargo.toml +++ b/calyx-utils/Cargo.toml @@ -23,3 +23,4 @@ string-interner.workspace = true itertools.workspace = true petgraph.workspace = true symbol_table = { version = "0.3", features = ["global"] } +lazy_static.workspace = true diff --git a/calyx-utils/src/position.rs b/calyx-utils/src/position.rs index 2b74e99a2..ade8ecbf8 100644 --- a/calyx-utils/src/position.rs +++ b/calyx-utils/src/position.rs @@ -1,7 +1,12 @@ //! Definitions for tracking source position information of Calyx programs use itertools::Itertools; -use std::{cmp, fmt::Write, mem, sync}; +use lazy_static::lazy_static; +use std::{ + cmp, + fmt::Write, + sync::{RwLock, RwLockWriteGuard}, +}; #[derive(Clone, Copy, PartialEq, Eq, Debug)] /// Handle to a position in a [PositionTable] @@ -99,28 +104,30 @@ impl PositionTable { /// The global position table pub struct GlobalPositionTable; +lazy_static! { + static ref GPOS_TABLE: RwLock = + RwLock::new(PositionTable::default()); +} + impl GlobalPositionTable { - /// Return reference to a global [PositionTable] - pub fn as_mut() -> &'static mut PositionTable { - static mut SINGLETON: mem::MaybeUninit = - mem::MaybeUninit::uninit(); - static ONCE: sync::Once = sync::Once::new(); - - // SAFETY: - // - writing to the singleton is OK because we only do it one time - // - the ONCE guarantees that SINGLETON is init'ed before assume_init_ref - unsafe { - ONCE.call_once(|| { - SINGLETON.write(PositionTable::new()); - assert!(PositionTable::UNKNOWN == GPosIdx::UNKNOWN.0) - }); - SINGLETON.assume_init_mut() - } + /// Return reference to a global [PositionTable]. + /// + /// # Safety + /// + /// You may not call this function after any call to [`Self::as_ref`]. + pub fn as_mut() -> RwLockWriteGuard<'static, PositionTable> { + GPOS_TABLE + .write() + .expect("failed to get write lock for global position table") } /// Return an immutable reference to the global position table pub fn as_ref() -> &'static PositionTable { - Self::as_mut() + &*Box::leak(Box::new( + GPOS_TABLE + .read() + .expect("failed to get read lock for global position table"), + )) } }