Revert removal of Arc from principal() and global()

This reverts commit c6d3bde0c6.
This reverts commit 4ce13f0adb.
This commit is contained in:
Mahmoud Al-Qudsi 2024-05-16 21:07:41 -05:00
parent c6d3bde0c6
commit 45e249dd94
6 changed files with 24 additions and 19 deletions

View File

@ -990,7 +990,7 @@ fn throwing_main() -> i32 {
}
}
OutputType::Ansi => {
colored_output = colorize(&output_wtext, &colors, EnvStack::globals());
colored_output = colorize(&output_wtext, &colors, &**EnvStack::globals());
}
OutputType::Html => {
colored_output = html_colorize(&output_wtext, &colors);

View File

@ -2473,7 +2473,7 @@ pub fn complete_load(cmd: &wstr, parser: &Parser) -> bool {
let path_to_load = completion_autoloader
.lock()
.expect("mutex poisoned")
.resolve_command(cmd, EnvStack::globals());
.resolve_command(cmd, &**EnvStack::globals());
if let Some(path_to_load) = path_to_load {
Autoload::perform_autoload(&path_to_load, parser);
completion_autoloader

View File

@ -188,7 +188,7 @@ impl EnvStack {
/// Return whether we are the principal stack.
pub fn is_principal(&self) -> bool {
std::ptr::eq(self, Self::principal())
std::ptr::eq(self, &**Self::principal())
}
/// Helpers to get and set the proc statuses.
@ -360,17 +360,17 @@ impl EnvStack {
/// A variable stack that only represents globals.
/// Do not push or pop from this.
pub fn globals() -> &'static EnvStack {
pub fn globals() -> &'static Arc<EnvStack> {
use std::sync::OnceLock;
static GLOBALS: OnceLock<EnvStack> = OnceLock::new();
GLOBALS.get_or_init(|| EnvStack::new())
static GLOBALS: OnceLock<Arc<EnvStack>> = OnceLock::new();
&GLOBALS.get_or_init(|| Arc::new(EnvStack::new()))
}
/// Access the principal variable stack, associated with the principal parser.
pub fn principal() -> &'static EnvStack {
pub fn principal() -> &'static Arc<EnvStack> {
use std::sync::OnceLock;
static PRINCIPAL_STACK: OnceLock<EnvStack> = OnceLock::new();
&PRINCIPAL_STACK.get_or_init(|| EnvStack::new())
static PRINCIPAL_STACK: OnceLock<Arc<EnvStack>> = OnceLock::new();
&PRINCIPAL_STACK.get_or_init(|| Arc::new(EnvStack::new()))
}
pub fn set_argv(&self, argv: Vec<WString>) {
@ -554,7 +554,7 @@ fn setup_path() {
pub static INHERITED_VARS: OnceCell<HashMap<WString, WString>> = OnceCell::new();
pub fn env_init(paths: Option<&ConfigPaths>, do_uvars: bool, default_paths: bool) {
let vars = EnvStack::principal();
let vars = &**EnvStack::principal();
let env_iter: Vec<_> = std::env::vars_os()
.map(|(k, v)| (str2wcstring(k.as_bytes()), str2wcstring(v.as_bytes())))

View File

@ -122,7 +122,7 @@ pub fn load(name: &wstr, parser: &Parser) -> bool {
if funcset.allow_autoload(name) {
if let Some(path) = funcset
.autoloader
.resolve_command(name, EnvStack::globals())
.resolve_command(name, &**EnvStack::globals())
{
path_to_autoload = Some(path);
}

View File

@ -65,7 +65,7 @@ impl<'a> OperationContext<'a> {
// Return an operation context that contains only global variables, no parser, and never
// cancels.
pub fn globals() -> OperationContext<'static> {
OperationContext::background(EnvStack::globals(), EXPANSION_LIMIT_DEFAULT)
OperationContext::background(&**EnvStack::globals(), EXPANSION_LIMIT_DEFAULT)
}
/// Construct from a full set of properties.

View File

@ -402,13 +402,18 @@ impl Parser {
pub fn principal_parser() -> &'static Parser {
use std::cell::OnceCell;
static PRINCIPAL: MainThread<OnceCell<ParserRef>> = MainThread::new(OnceCell::new());
&PRINCIPAL.get().get_or_init(|| {
// Safety: EnvStack::principal() returns a `static` variable guaranteed to always be
// alive. We just don't want to hard-code the lifetime in `Parser` so we wrap the
// `EnvStack` in an `Rc` before sending it along.
let env_rc = unsafe { Rc::from_raw(EnvStack::principal() as *const _) };
Parser::new(env_rc, true)
})
&PRINCIPAL
.get()
// The parser is !Send/!Sync and strictly single-threaded, but we can have
// multi-threaded access to its variables stack (why, though?) so EnvStack::principal()
// returns an Arc<EnvStack> instead of an Rc<EnvStack>. Since the Arc<EnvStack> is
// statically allocated and always valid (not even destroyed on exit), we can safely
// transform the Arc<T> into an Rc<T> and save Parser from needing atomic ref counting
// to manage its further references.
.get_or_init(|| {
let env_rc = unsafe { Rc::from_raw(&**EnvStack::principal() as *const _) };
Parser::new(env_rc, true)
})
}
/// Assert that this parser is allowed to execute on the current thread.