1- //! Implementation of `StaticKey ` for Windows. 
1+ //! Implementation of `LazyKey ` for Windows. 
22//! 
33//! Windows has no native support for running destructors so we manage our own 
44//! list of destructors to keep track of how to destroy keys. We then install a 
1313//! don't reach a fixed point after a short while then we just inevitably leak 
1414//! something. 
1515//! 
16- //! The list is implemented as an atomic single-linked list of `StaticKey `s and 
16+ //! The list is implemented as an atomic single-linked list of `LazyKey `s and 
1717//! does not support unregistration. Unfortunately, this means that we cannot 
18- //! use racy initialization for creating the keys in `StaticKey `, as that could 
18+ //! use racy initialization for creating the keys in `LazyKey `, as that could 
1919//! result in destructors being missed. Hence, we synchronize the creation of 
2020//! keys with destructors through [`INIT_ONCE`](c::INIT_ONCE) (`std`'s 
2121//! [`Once`](crate::sync::Once) cannot be used since it might use TLS itself). 
@@ -33,26 +33,26 @@ use crate::sync::atomic::{
3333use  crate :: sys:: c; 
3434use  crate :: sys:: thread_local:: guard; 
3535
36- type  Key  = c:: DWORD ; 
36+ pub   type  Key  = c:: DWORD ; 
3737type  Dtor  = unsafe  extern  "C"  fn ( * mut  u8 ) ; 
3838
39- pub  struct  StaticKey  { 
39+ pub  struct  LazyKey  { 
4040    /// The key value shifted up by one. Since TLS_OUT_OF_INDEXES == DWORD::MAX 
4141/// is not a valid key value, this allows us to use zero as sentinel value 
4242/// without risking overflow. 
4343key :  AtomicU32 , 
4444    dtor :  Option < Dtor > , 
45-     next :  AtomicPtr < StaticKey > , 
45+     next :  AtomicPtr < LazyKey > , 
4646    /// Currently, destructors cannot be unregistered, so we cannot use racy 
4747/// initialization for keys. Instead, we need synchronize initialization. 
4848/// Use the Windows-provided `Once` since it does not require TLS. 
4949once :  UnsafeCell < c:: INIT_ONCE > , 
5050} 
5151
52- impl  StaticKey  { 
52+ impl  LazyKey  { 
5353    #[ inline]  
54-     pub  const  fn  new ( dtor :  Option < Dtor > )  -> StaticKey  { 
55-         StaticKey  { 
54+     pub  const  fn  new ( dtor :  Option < Dtor > )  -> LazyKey  { 
55+         LazyKey  { 
5656            key :  AtomicU32 :: new ( 0 ) , 
5757            dtor, 
5858            next :  AtomicPtr :: new ( ptr:: null_mut ( ) ) , 
@@ -61,18 +61,7 @@ impl StaticKey {
6161    } 
6262
6363    #[ inline]  
64-     pub  unsafe  fn  set ( & ' static  self ,  val :  * mut  u8 )  { 
65-         let  r = unsafe  {  c:: TlsSetValue ( self . key ( ) ,  val. cast ( ) )  } ; 
66-         debug_assert_eq ! ( r,  c:: TRUE ) ; 
67-     } 
68- 
69-     #[ inline]  
70-     pub  unsafe  fn  get ( & ' static  self )  -> * mut  u8  { 
71-         unsafe  {  c:: TlsGetValue ( self . key ( ) ) . cast ( )  } 
72-     } 
73- 
74-     #[ inline]  
75-     fn  key ( & ' static  self )  -> Key  { 
64+     pub  fn  force ( & ' static  self )  -> Key  { 
7665        match  self . key . load ( Acquire )  { 
7766            0  => unsafe  {  self . init ( )  } , 
7867            key => key - 1 , 
@@ -141,17 +130,28 @@ impl StaticKey {
141130    } 
142131} 
143132
144- unsafe  impl  Send  for  StaticKey  { } 
145- unsafe  impl  Sync  for  StaticKey  { } 
133+ unsafe  impl  Send  for  LazyKey  { } 
134+ unsafe  impl  Sync  for  LazyKey  { } 
135+ 
136+ #[ inline]  
137+ pub  unsafe  fn  set ( key :  Key ,  val :  * mut  u8 )  { 
138+     let  r = unsafe  {  c:: TlsSetValue ( key,  val. cast ( ) )  } ; 
139+     debug_assert_eq ! ( r,  c:: TRUE ) ; 
140+ } 
141+ 
142+ #[ inline]  
143+ pub  unsafe  fn  get ( key :  Key )  -> * mut  u8  { 
144+     unsafe  {  c:: TlsGetValue ( key) . cast ( )  } 
145+ } 
146146
147- static  DTORS :  AtomicPtr < StaticKey >  = AtomicPtr :: new ( ptr:: null_mut ( ) ) ; 
147+ static  DTORS :  AtomicPtr < LazyKey >  = AtomicPtr :: new ( ptr:: null_mut ( ) ) ; 
148148
149149/// Should only be called once per key, otherwise loops or breaks may occur in 
150150/// the linked list. 
151- unsafe  fn  register_dtor ( key :  & ' static  StaticKey )  { 
151+ unsafe  fn  register_dtor ( key :  & ' static  LazyKey )  { 
152152    guard:: enable ( ) ; 
153153
154-     let  this = <* const  StaticKey >:: cast_mut ( key) ; 
154+     let  this = <* const  LazyKey >:: cast_mut ( key) ; 
155155    // Use acquire ordering to pass along the changes done by the previously 
156156    // registered keys when we store the new head with release ordering. 
157157    let  mut  head = DTORS . load ( Acquire ) ; 
@@ -176,9 +176,9 @@ pub unsafe fn run_dtors() {
176176            let  dtor = unsafe  {  ( * cur) . dtor . unwrap ( )  } ; 
177177            cur = unsafe  {  ( * cur) . next . load ( Relaxed )  } ; 
178178
179-             // In StaticKey ::init, we register the dtor before setting `key`. 
179+             // In LazyKey ::init, we register the dtor before setting `key`. 
180180            // So if one thread's `run_dtors` races with another thread executing `init` on the same 
181-             // `StaticKey `, we can encounter a key of 0 here. That means this key was never 
181+             // `LazyKey `, we can encounter a key of 0 here. That means this key was never 
182182            // initialized in this thread so we can safely skip it. 
183183            if  pre_key == 0  { 
184184                continue ; 
0 commit comments