diff options
Diffstat (limited to 'src/libstd')
| -rw-r--r-- | src/libstd/io/lazy.rs | 38 | ||||
| -rw-r--r-- | src/libstd/io/stdio.rs | 20 | ||||
| -rw-r--r-- | src/libstd/lib.rs | 3 | ||||
| -rw-r--r-- | src/libstd/sys/cloudabi/condvar.rs | 8 | ||||
| -rw-r--r-- | src/libstd/sys/cloudabi/rwlock.rs | 8 |
5 files changed, 42 insertions, 35 deletions
diff --git a/src/libstd/io/lazy.rs b/src/libstd/io/lazy.rs index 4fb367fb6ba..24965ff6931 100644 --- a/src/libstd/io/lazy.rs +++ b/src/libstd/io/lazy.rs @@ -18,7 +18,6 @@ pub struct Lazy<T> { // We never call `lock.init()`, so it is UB to attempt to acquire this mutex reentrantly! lock: Mutex, ptr: Cell<*mut Arc<T>>, - init: fn() -> Arc<T>, } #[inline] @@ -26,33 +25,32 @@ const fn done<T>() -> *mut Arc<T> { 1_usize as *mut _ } unsafe impl<T> Sync for Lazy<T> {} -impl<T: Send + Sync + 'static> Lazy<T> { - /// Safety: `init` must not call `get` on the variable that is being - /// initialized. - pub const unsafe fn new(init: fn() -> Arc<T>) -> Lazy<T> { +impl<T> Lazy<T> { + pub const fn new() -> Lazy<T> { Lazy { lock: Mutex::new(), ptr: Cell::new(ptr::null_mut()), - init, } } +} - pub fn get(&'static self) -> Option<Arc<T>> { - unsafe { - let _guard = self.lock.lock(); - let ptr = self.ptr.get(); - if ptr.is_null() { - Some(self.init()) - } else if ptr == done() { - None - } else { - Some((*ptr).clone()) - } +impl<T: Send + Sync + 'static> Lazy<T> { + /// Safety: `init` must not call `get` on the variable that is being + /// initialized. + pub unsafe fn get(&'static self, init: fn() -> Arc<T>) -> Option<Arc<T>> { + let _guard = self.lock.lock(); + let ptr = self.ptr.get(); + if ptr.is_null() { + Some(self.init(init)) + } else if ptr == done() { + None + } else { + Some((*ptr).clone()) } } // Must only be called with `lock` held - unsafe fn init(&'static self) -> Arc<T> { + unsafe fn init(&'static self, init: fn() -> Arc<T>) -> Arc<T> { // If we successfully register an at exit handler, then we cache the // `Arc` allocation in our own internal box (it will get deallocated by // the at exit handler). Otherwise we just return the freshly allocated @@ -66,8 +64,8 @@ impl<T: Send + Sync + 'static> Lazy<T> { }); // This could reentrantly call `init` again, which is a problem // because our `lock` allows reentrancy! - // That's why `new` is unsafe and requires the caller to ensure no reentrancy happens. - let ret = (self.init)(); + // That's why `get` is unsafe and requires the caller to ensure no reentrancy happens. + let ret = init(); if registered.is_ok() { self.ptr.set(Box::into_raw(Box::new(ret.clone()))); } diff --git a/src/libstd/io/stdio.rs b/src/libstd/io/stdio.rs index 1f256f518c7..a413432cdaa 100644 --- a/src/libstd/io/stdio.rs +++ b/src/libstd/io/stdio.rs @@ -197,9 +197,11 @@ pub struct StdinLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdin() -> Stdin { - static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = unsafe { Lazy::new(stdin_init) }; + static INSTANCE: Lazy<Mutex<BufReader<Maybe<StdinRaw>>>> = Lazy::new(); return Stdin { - inner: INSTANCE.get().expect("cannot access stdin during shutdown"), + inner: unsafe { + INSTANCE.get(stdin_init).expect("cannot access stdin during shutdown") + }, }; fn stdin_init() -> Arc<Mutex<BufReader<Maybe<StdinRaw>>>> { @@ -396,10 +398,11 @@ pub struct StdoutLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stdout() -> Stdout { - static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> - = unsafe { Lazy::new(stdout_init) }; + static INSTANCE: Lazy<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> = Lazy::new(); return Stdout { - inner: INSTANCE.get().expect("cannot access stdout during shutdown"), + inner: unsafe { + INSTANCE.get(stdout_init).expect("cannot access stdout during shutdown") + }, }; fn stdout_init() -> Arc<ReentrantMutex<RefCell<LineWriter<Maybe<StdoutRaw>>>>> { @@ -533,10 +536,11 @@ pub struct StderrLock<'a> { /// ``` #[stable(feature = "rust1", since = "1.0.0")] pub fn stderr() -> Stderr { - static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = - unsafe { Lazy::new(stderr_init) }; + static INSTANCE: Lazy<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> = Lazy::new(); return Stderr { - inner: INSTANCE.get().expect("cannot access stderr during shutdown"), + inner: unsafe { + INSTANCE.get(stderr_init).expect("cannot access stderr during shutdown") + }, }; fn stderr_init() -> Arc<ReentrantMutex<RefCell<Maybe<StderrRaw>>>> { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 310475d31fd..e7195b3e21e 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -250,7 +250,8 @@ #![feature(cfg_target_vendor)] #![feature(char_error_internals)] #![feature(compiler_builtins_lib)] -#![feature(const_fn)] +#![cfg_attr(stage0, feature(const_fn))] +#![cfg_attr(not(stage0), feature(min_const_fn))] #![feature(const_int_ops)] #![feature(const_ip)] #![feature(core_intrinsics)] diff --git a/src/libstd/sys/cloudabi/condvar.rs b/src/libstd/sys/cloudabi/condvar.rs index c05c837ade2..ccf848a9be4 100644 --- a/src/libstd/sys/cloudabi/condvar.rs +++ b/src/libstd/sys/cloudabi/condvar.rs @@ -28,11 +28,13 @@ pub struct Condvar { unsafe impl Send for Condvar {} unsafe impl Sync for Condvar {} +const NEW: Condvar = Condvar { + condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)), +}; + impl Condvar { pub const fn new() -> Condvar { - Condvar { - condvar: UnsafeCell::new(AtomicU32::new(abi::CONDVAR_HAS_NO_WAITERS.0)), - } + NEW } pub unsafe fn init(&mut self) {} diff --git a/src/libstd/sys/cloudabi/rwlock.rs b/src/libstd/sys/cloudabi/rwlock.rs index 8539aec5e2c..dc8624ec8a1 100644 --- a/src/libstd/sys/cloudabi/rwlock.rs +++ b/src/libstd/sys/cloudabi/rwlock.rs @@ -32,11 +32,13 @@ pub unsafe fn raw(r: &RWLock) -> *mut AtomicU32 { unsafe impl Send for RWLock {} unsafe impl Sync for RWLock {} +const NEW: RWLock = RWLock { + lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)), +}; + impl RWLock { pub const fn new() -> RWLock { - RWLock { - lock: UnsafeCell::new(AtomicU32::new(abi::LOCK_UNLOCKED.0)), - } + NEW } pub unsafe fn try_read(&self) -> bool { |
