diff --git a/src/libcore/os.rs b/src/libcore/os.rs index aa4a6feb76f71..caca929d64cae 100644 --- a/src/libcore/os.rs +++ b/src/libcore/os.rs @@ -39,6 +39,7 @@ use str; use task; use uint; use vec; +use unstable::global::with_global_lock; pub use libc::fclose; pub use os::consts::*; @@ -151,23 +152,6 @@ Accessing environment variables is not generally threadsafe. This uses a per-runtime lock to serialize access. FIXME #4726: It would probably be appropriate to make this a real global */ -fn with_env_lock(f: &fn() -> T) -> T { - use unstable::global::global_data_clone_create; - use unstable::{Exclusive, exclusive}; - - struct SharedValue(()); - type ValueMutex = Exclusive; - fn key(_: ValueMutex) { } - - unsafe { - let lock: ValueMutex = global_data_clone_create(key, || { - ~exclusive(SharedValue(())) - }); - - lock.with_imm(|_| f() ) - } -} - pub fn env() -> ~[(~str,~str)] { unsafe { #[cfg(windows)] @@ -227,7 +211,8 @@ pub fn env() -> ~[(~str,~str)] { } pairs } - do with_env_lock { + + do with_global_lock { let unparsed_environ = get_env_pairs(); env_convert(unparsed_environ) } @@ -237,7 +222,7 @@ pub fn env() -> ~[(~str,~str)] { #[cfg(unix)] pub fn getenv(n: &str) -> Option<~str> { unsafe { - do with_env_lock { + do with_global_lock { let s = str::as_c_str(n, |s| libc::getenv(s)); if ptr::null::() == cast::reinterpret_cast(&s) { option::None::<~str> @@ -252,7 +237,7 @@ pub fn getenv(n: &str) -> Option<~str> { #[cfg(windows)] pub fn getenv(n: &str) -> Option<~str> { unsafe { - do with_env_lock { + do with_global_lock { use os::win32::{as_utf16_p, fill_utf16_buf_and_decode}; do as_utf16_p(n) |u| { do fill_utf16_buf_and_decode() |buf, sz| { @@ -267,7 +252,7 @@ pub fn getenv(n: &str) -> Option<~str> { #[cfg(unix)] pub fn setenv(n: &str, v: &str) { unsafe { - do with_env_lock { + do with_global_lock { do str::as_c_str(n) |nbuf| { do str::as_c_str(v) |vbuf| { libc::funcs::posix01::unistd::setenv(nbuf, vbuf, 1); @@ -281,7 +266,7 @@ pub fn setenv(n: &str, v: &str) { #[cfg(windows)] pub fn setenv(n: &str, v: &str) { unsafe { - do with_env_lock { + do with_global_lock { use os::win32::as_utf16_p; do as_utf16_p(n) |nbuf| { do as_utf16_p(v) |vbuf| { diff --git a/src/libcore/unstable/global.rs b/src/libcore/unstable/global.rs index 654bf18a5b6b9..063db1159363e 100644 --- a/src/libcore/unstable/global.rs +++ b/src/libcore/unstable/global.rs @@ -157,6 +157,20 @@ impl Drop for GlobalState { } } +pub unsafe fn with_global_lock(f: &fn() -> T) -> T { + struct SharedValue(()); + type ValueMutex = Exclusive; + fn key(_: ValueMutex) { } + + unsafe { + let lock: ValueMutex = global_data_clone_create(key, || { + ~exclusive(SharedValue(())) + }); + + lock.with_imm(|_| f() ) + } +} + fn get_global_state() -> Exclusive { const POISON: int = -1; diff --git a/src/libstd/rl.rs b/src/libstd/rl.rs index a8b25767ce595..1db2990b4c5be 100644 --- a/src/libstd/rl.rs +++ b/src/libstd/rl.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -15,6 +15,7 @@ use core::libc::{c_char, c_int}; use core::prelude::*; use core::str; use core::task; +use core::unstable::global::with_global_lock; pub mod rustrt { use core::libc::{c_char, c_int}; @@ -30,29 +31,43 @@ pub mod rustrt { } } +/* +The linenoise library is not threadsafe, +This uses a per-runtime lock to serialize access. +FIXME #4726: It would probably be appropriate to make this a real global +*/ + /// Add a line to history pub unsafe fn add_history(line: ~str) -> bool { - do str::as_c_str(line) |buf| { - rustrt::linenoiseHistoryAdd(buf) == 1 as c_int + do with_global_lock { + do str::as_c_str(line) |buf| { + rustrt::linenoiseHistoryAdd(buf) == 1 as c_int + } } } /// Set the maximum amount of lines stored pub unsafe fn set_history_max_len(len: int) -> bool { - rustrt::linenoiseHistorySetMaxLen(len as c_int) == 1 as c_int + do with_global_lock { + rustrt::linenoiseHistorySetMaxLen(len as c_int) == 1 as c_int + } } /// Save line history to a file pub unsafe fn save_history(file: ~str) -> bool { - do str::as_c_str(file) |buf| { - rustrt::linenoiseHistorySave(buf) == 1 as c_int + do with_global_lock { + do str::as_c_str(file) |buf| { + rustrt::linenoiseHistorySave(buf) == 1 as c_int + } } } /// Load line history from a file pub unsafe fn load_history(file: ~str) -> bool { - do str::as_c_str(file) |buf| { - rustrt::linenoiseHistoryLoad(buf) == 1 as c_int + do with_global_lock { + do str::as_c_str(file) |buf| { + rustrt::linenoiseHistoryLoad(buf) == 1 as c_int + } } }