use core::{marker, mem};
use shim::thread_destructor;
pub struct Key<T: 'static> {
inner: T,
}
impl<T: 'static> Key<T> {
pub const unsafe fn new(inner: T) -> Key<T> {
Key { inner: inner }
}
#[inline]
pub fn with<F, R>(&'static self, f: F) -> R
where F: FnOnce(&T) -> R {
log!(INTERNAL, "Accessing TLS variable.");
f(&self.inner)
}
#[inline]
pub fn register_thread_destructor(&'static self, dtor: extern fn(&T)) {
log!(INTERNAL, "Registering thread destructor.");
thread_destructor::register(&self.inner as *const T as *const u8 as *mut u8, unsafe {
mem::transmute(dtor)
});
}
}
unsafe impl<T> marker::Sync for Key<T> {}
macro_rules! tls {
(static $name:ident: $ty:ty = $val:expr;) => { tls! { #[] static $name: $ty = $val; } };
(#[$($attr:meta),*] static $name:ident: $ty:ty = $val:expr;) => {
$(#[$attr])*
#[thread_local]
static $name: tls::Key<$ty> = unsafe {
tls::Key::new($val)
};
}
}