Skip to content

Commit b812b77

Browse files
committed
Rollup merge of rust-lang#48585 - stjepang:stabilize-localkey-try_with, r=alexcrichton
Stabilize LocalKey::try_with The `LocalKey::try_with` method is now stabilized. `LocalKey::state` and `LocalKeyState` marked as deprecated. Although, is there any reason to keep them - should we perhaps remove them completely? Closes rust-lang#27716 r? @alexcrichton
2 parents 8025e15 + cb56b2d commit b812b77

File tree

5 files changed

+43
-141
lines changed

5 files changed

+43
-141
lines changed

src/libstd/io/stdio.rs

+22-20
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use io::{self, Initializer, BufReader, LineWriter};
1717
use sync::{Arc, Mutex, MutexGuard};
1818
use sys::stdio;
1919
use sys_common::remutex::{ReentrantMutex, ReentrantMutexGuard};
20-
use thread::{LocalKey, LocalKeyState};
20+
use thread::LocalKey;
2121

2222
/// Stdout used by print! and println! macros
2323
thread_local! {
@@ -663,29 +663,31 @@ pub fn set_print(sink: Option<Box<Write + Send>>) -> Option<Box<Write + Send>> {
663663
///
664664
/// This function is used to print error messages, so it takes extra
665665
/// care to avoid causing a panic when `local_stream` is unusable.
666-
/// For instance, if the TLS key for the local stream is uninitialized
667-
/// or already destroyed, or if the local stream is locked by another
666+
/// For instance, if the TLS key for the local stream is
667+
/// already destroyed, or if the local stream is locked by another
668668
/// thread, it will just fall back to the global stream.
669669
///
670670
/// However, if the actual I/O causes an error, this function does panic.
671-
fn print_to<T>(args: fmt::Arguments,
672-
local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
673-
global_s: fn() -> T,
674-
label: &str) where T: Write {
675-
let result = match local_s.state() {
676-
LocalKeyState::Uninitialized |
677-
LocalKeyState::Destroyed => global_s().write_fmt(args),
678-
LocalKeyState::Valid => {
679-
local_s.with(|s| {
680-
if let Ok(mut borrowed) = s.try_borrow_mut() {
681-
if let Some(w) = borrowed.as_mut() {
682-
return w.write_fmt(args);
683-
}
684-
}
685-
global_s().write_fmt(args)
686-
})
671+
fn print_to<T>(
672+
args: fmt::Arguments,
673+
local_s: &'static LocalKey<RefCell<Option<Box<Write+Send>>>>,
674+
global_s: fn() -> T,
675+
label: &str,
676+
)
677+
where
678+
T: Write,
679+
{
680+
let result = local_s.try_with(|s| {
681+
if let Ok(mut borrowed) = s.try_borrow_mut() {
682+
if let Some(w) = borrowed.as_mut() {
683+
return w.write_fmt(args);
684+
}
687685
}
688-
};
686+
global_s().write_fmt(args)
687+
}).unwrap_or_else(|_| {
688+
global_s().write_fmt(args)
689+
});
690+
689691
if let Err(e) = result {
690692
panic!("failed printing to {}: {}", label, e);
691693
}

src/libstd/thread/local.rs

+15-113
Original file line numberDiff line numberDiff line change
@@ -195,64 +195,20 @@ macro_rules! __thread_local_inner {
195195
}
196196
}
197197

198-
/// Indicator of the state of a thread local storage key.
199-
#[unstable(feature = "thread_local_state",
200-
reason = "state querying was recently added",
201-
issue = "27716")]
202-
#[derive(Debug, Eq, PartialEq, Copy, Clone)]
203-
pub enum LocalKeyState {
204-
/// All keys are in this state whenever a thread starts. Keys will
205-
/// transition to the `Valid` state once the first call to [`with`] happens
206-
/// and the initialization expression succeeds.
207-
///
208-
/// Keys in the `Uninitialized` state will yield a reference to the closure
209-
/// passed to [`with`] so long as the initialization routine does not panic.
210-
///
211-
/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
212-
Uninitialized,
213-
214-
/// Once a key has been accessed successfully, it will enter the `Valid`
215-
/// state. Keys in the `Valid` state will remain so until the thread exits,
216-
/// at which point the destructor will be run and the key will enter the
217-
/// `Destroyed` state.
218-
///
219-
/// Keys in the `Valid` state will be guaranteed to yield a reference to the
220-
/// closure passed to [`with`].
221-
///
222-
/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
223-
Valid,
224-
225-
/// When a thread exits, the destructors for keys will be run (if
226-
/// necessary). While a destructor is running, and possibly after a
227-
/// destructor has run, a key is in the `Destroyed` state.
228-
///
229-
/// Keys in the `Destroyed` states will trigger a panic when accessed via
230-
/// [`with`].
231-
///
232-
/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
233-
Destroyed,
234-
}
235-
236198
/// An error returned by [`LocalKey::try_with`](struct.LocalKey.html#method.try_with).
237-
#[unstable(feature = "thread_local_state",
238-
reason = "state querying was recently added",
239-
issue = "27716")]
199+
#[stable(feature = "thread_local_try_with", since = "1.26.0")]
240200
pub struct AccessError {
241201
_private: (),
242202
}
243203

244-
#[unstable(feature = "thread_local_state",
245-
reason = "state querying was recently added",
246-
issue = "27716")]
204+
#[stable(feature = "thread_local_try_with", since = "1.26.0")]
247205
impl fmt::Debug for AccessError {
248206
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
249207
f.debug_struct("AccessError").finish()
250208
}
251209
}
252210

253-
#[unstable(feature = "thread_local_state",
254-
reason = "state querying was recently added",
255-
issue = "27716")]
211+
#[stable(feature = "thread_local_try_with", since = "1.26.0")]
256212
impl fmt::Display for AccessError {
257213
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
258214
fmt::Display::fmt("already destroyed", f)
@@ -312,64 +268,21 @@ impl<T: 'static> LocalKey<T> {
312268
(*ptr).as_ref().unwrap()
313269
}
314270

315-
/// Query the current state of this key.
316-
///
317-
/// A key is initially in the `Uninitialized` state whenever a thread
318-
/// starts. It will remain in this state up until the first call to [`with`]
319-
/// within a thread has run the initialization expression successfully.
320-
///
321-
/// Once the initialization expression succeeds, the key transitions to the
322-
/// `Valid` state which will guarantee that future calls to [`with`] will
323-
/// succeed within the thread. Some keys might skip the `Uninitialized`
324-
/// state altogether and start in the `Valid` state as an optimization
325-
/// (e.g. keys initialized with a constant expression), but no guarantees
326-
/// are made.
327-
///
328-
/// When a thread exits, each key will be destroyed in turn, and as keys are
329-
/// destroyed they will enter the `Destroyed` state just before the
330-
/// destructor starts to run. Keys may remain in the `Destroyed` state after
331-
/// destruction has completed. Keys without destructors (e.g. with types
332-
/// that are [`Copy`]), may never enter the `Destroyed` state.
333-
///
334-
/// Keys in the `Uninitialized` state can be accessed so long as the
335-
/// initialization does not panic. Keys in the `Valid` state are guaranteed
336-
/// to be able to be accessed. Keys in the `Destroyed` state will panic on
337-
/// any call to [`with`].
338-
///
339-
/// [`with`]: ../../std/thread/struct.LocalKey.html#method.with
340-
/// [`Copy`]: ../../std/marker/trait.Copy.html
341-
#[unstable(feature = "thread_local_state",
342-
reason = "state querying was recently added",
343-
issue = "27716")]
344-
pub fn state(&'static self) -> LocalKeyState {
345-
unsafe {
346-
match (self.inner)() {
347-
Some(cell) => {
348-
match *cell.get() {
349-
Some(..) => LocalKeyState::Valid,
350-
None => LocalKeyState::Uninitialized,
351-
}
352-
}
353-
None => LocalKeyState::Destroyed,
354-
}
355-
}
356-
}
357-
358271
/// Acquires a reference to the value in this TLS key.
359272
///
360273
/// This will lazily initialize the value if this thread has not referenced
361274
/// this key yet. If the key has been destroyed (which may happen if this is called
362-
/// in a destructor), this function will return a ThreadLocalError.
275+
/// in a destructor), this function will return a `ThreadLocalError`.
363276
///
364277
/// # Panics
365278
///
366279
/// This function will still `panic!()` if the key is uninitialized and the
367280
/// key's initializer panics.
368-
#[unstable(feature = "thread_local_state",
369-
reason = "state querying was recently added",
370-
issue = "27716")]
281+
#[stable(feature = "thread_local_try_with", since = "1.26.0")]
371282
pub fn try_with<F, R>(&'static self, f: F) -> Result<R, AccessError>
372-
where F: FnOnce(&T) -> R {
283+
where
284+
F: FnOnce(&T) -> R,
285+
{
373286
unsafe {
374287
let slot = (self.inner)().ok_or(AccessError {
375288
_private: (),
@@ -530,7 +443,6 @@ pub mod os {
530443
mod tests {
531444
use sync::mpsc::{channel, Sender};
532445
use cell::{Cell, UnsafeCell};
533-
use super::LocalKeyState;
534446
use thread;
535447

536448
struct Foo(Sender<()>);
@@ -569,21 +481,13 @@ mod tests {
569481
struct Foo;
570482
impl Drop for Foo {
571483
fn drop(&mut self) {
572-
assert!(FOO.state() == LocalKeyState::Destroyed);
484+
assert!(FOO.try_with(|_| ()).is_err());
573485
}
574486
}
575-
fn foo() -> Foo {
576-
assert!(FOO.state() == LocalKeyState::Uninitialized);
577-
Foo
578-
}
579-
thread_local!(static FOO: Foo = foo());
487+
thread_local!(static FOO: Foo = Foo);
580488

581489
thread::spawn(|| {
582-
assert!(FOO.state() == LocalKeyState::Uninitialized);
583-
FOO.with(|_| {
584-
assert!(FOO.state() == LocalKeyState::Valid);
585-
});
586-
assert!(FOO.state() == LocalKeyState::Valid);
490+
assert!(FOO.try_with(|_| ()).is_ok());
587491
}).join().ok().unwrap();
588492
}
589493

@@ -613,7 +517,7 @@ mod tests {
613517
fn drop(&mut self) {
614518
unsafe {
615519
HITS += 1;
616-
if K2.state() == LocalKeyState::Destroyed {
520+
if K2.try_with(|_| ()).is_err() {
617521
assert_eq!(HITS, 3);
618522
} else {
619523
if HITS == 1 {
@@ -629,7 +533,7 @@ mod tests {
629533
fn drop(&mut self) {
630534
unsafe {
631535
HITS += 1;
632-
assert!(K1.state() != LocalKeyState::Destroyed);
536+
assert!(K1.try_with(|_| ()).is_ok());
633537
assert_eq!(HITS, 2);
634538
K1.with(|s| *s.get() = Some(S1));
635539
}
@@ -648,7 +552,7 @@ mod tests {
648552

649553
impl Drop for S1 {
650554
fn drop(&mut self) {
651-
assert!(K1.state() == LocalKeyState::Destroyed);
555+
assert!(K1.try_with(|_| ()).is_err());
652556
}
653557
}
654558

@@ -672,9 +576,7 @@ mod tests {
672576
fn drop(&mut self) {
673577
let S1(ref tx) = *self;
674578
unsafe {
675-
if K2.state() != LocalKeyState::Destroyed {
676-
K2.with(|s| *s.get() = Some(Foo(tx.clone())));
677-
}
579+
let _ = K2.try_with(|s| *s.get() = Some(Foo(tx.clone())));
678580
}
679581
}
680582
}

src/libstd/thread/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ use time::Duration;
191191
#[macro_use] mod local;
192192

193193
#[stable(feature = "rust1", since = "1.0.0")]
194-
pub use self::local::{LocalKey, LocalKeyState, AccessError};
194+
pub use self::local::{LocalKey, AccessError};
195195

196196
// The types used by the thread_local! macro to access TLS keys. Note that there
197197
// are two types, the "OS" type and the "fast" type. The OS thread local key

src/test/run-pass/tls-init-on-init.rs

+4-6
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@
1010

1111
// ignore-emscripten no threads support
1212

13-
#![feature(thread_local_state)]
13+
#![feature(thread_local_try_with)]
1414

15-
use std::thread::{self, LocalKeyState};
15+
use std::thread;
1616
use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
1717

1818
struct Foo { cnt: usize }
@@ -37,10 +37,8 @@ impl Drop for Foo {
3737
FOO.with(|foo| assert_eq!(foo.cnt, 0));
3838
} else {
3939
assert_eq!(self.cnt, 0);
40-
match FOO.state() {
41-
LocalKeyState::Valid => panic!("should not be in valid state"),
42-
LocalKeyState::Uninitialized |
43-
LocalKeyState::Destroyed => {}
40+
if FOO.try_with(|_| ()).is_ok() {
41+
panic!("should not be in valid state");
4442
}
4543
}
4644
}

src/test/run-pass/tls-try-with.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
// ignore-emscripten no threads support
1212

13-
#![feature(thread_local_state)]
13+
#![feature(thread_local_try_with)]
1414

1515
use std::thread;
1616

0 commit comments

Comments
 (0)