1 use std::fmt::{self, Debug};
2 use std::thread::{self, ThreadId};
3 
4 /// ThreadBound is a Sync-maker and Send-maker that allows accessing a value
5 /// of type T only from the original thread on which the ThreadBound was
6 /// constructed.
7 pub(crate) struct ThreadBound<T> {
8     value: T,
9     thread_id: ThreadId,
10 }
11 
12 unsafe impl<T> Sync for ThreadBound<T> {}
13 
14 // Send bound requires Copy, as otherwise Drop could run in the wrong place.
15 //
16 // Today Copy and Drop are mutually exclusive so `T: Copy` implies `T: !Drop`.
17 // This impl needs to be revisited if that restriction is relaxed in the future.
18 unsafe impl<T: Copy> Send for ThreadBound<T> {}
19 
20 impl<T> ThreadBound<T> {
new(value: T) -> Self21     pub(crate) fn new(value: T) -> Self {
22         ThreadBound {
23             value,
24             thread_id: thread::current().id(),
25         }
26     }
27 
get(&self) -> Option<&T>28     pub(crate) fn get(&self) -> Option<&T> {
29         if thread::current().id() == self.thread_id {
30             Some(&self.value)
31         } else {
32             None
33         }
34     }
35 }
36 
37 impl<T: Debug> Debug for ThreadBound<T> {
fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result38     fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
39         match self.get() {
40             Some(value) => Debug::fmt(value, formatter),
41             None => formatter.write_str("unknown"),
42         }
43     }
44 }
45 
46 // Copy the bytes of T, even if the currently running thread is the "wrong"
47 // thread. This is fine as long as the original thread is not simultaneously
48 // mutating this value via interior mutability, which would be a data race.
49 //
50 // Currently `T: Copy` is sufficient to guarantee that T contains no interior
51 // mutability, because _all_ interior mutability in Rust is built on
52 // std::cell::UnsafeCell, which has no Copy impl. This impl needs to be
53 // revisited if that restriction is relaxed in the future.
54 impl<T: Copy> Copy for ThreadBound<T> {}
55 
56 impl<T: Copy> Clone for ThreadBound<T> {
clone(&self) -> Self57     fn clone(&self) -> Self {
58         *self
59     }
60 }
61