// SPDX-License-Identifier: Apache-2.0 OR MIT12use std::fmt::{self, Debug};3use std::thread::{self, ThreadId};45/// ThreadBound is a Sync-maker and Send-maker that allows accessing a value6/// of type T only from the original thread on which the ThreadBound was7/// constructed.8pub(crate) struct ThreadBound<T> {9value: T,10thread_id: ThreadId,11}1213unsafe impl<T> Sync for ThreadBound<T> {}1415// Send bound requires Copy, as otherwise Drop could run in the wrong place.16//17// Today Copy and Drop are mutually exclusive so `T: Copy` implies `T: !Drop`.18// This impl needs to be revisited if that restriction is relaxed in the future.19unsafe impl<T: Copy> Send for ThreadBound<T> {}2021impl<T> ThreadBound<T> {22pub(crate) fn new(value: T) -> Self {23ThreadBound {24value,25thread_id: thread::current().id(),26}27}2829pub(crate) fn get(&self) -> Option<&T> {30if thread::current().id() == self.thread_id {31Some(&self.value)32} else {33None34}35}36}3738impl<T: Debug> Debug for ThreadBound<T> {39fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {40match self.get() {41Some(value) => Debug::fmt(value, formatter),42None => formatter.write_str("unknown"),43}44}45}4647// Copy the bytes of T, even if the currently running thread is the "wrong"48// thread. This is fine as long as the original thread is not simultaneously49// mutating this value via interior mutability, which would be a data race.50//51// Currently `T: Copy` is sufficient to guarantee that T contains no interior52// mutability, because _all_ interior mutability in Rust is built on53// std::cell::UnsafeCell, which has no Copy impl. This impl needs to be54// revisited if that restriction is relaxed in the future.55impl<T: Copy> Copy for ThreadBound<T> {}5657impl<T: Copy> Clone for ThreadBound<T> {58fn clone(&self) -> Self {59*self60}61}626364