77//! `GetModuleHandle` and `GetProcAddress` to look up DLL entry points at
88//! runtime.
99//!
10- //! This is implemented simply by storing a function pointer in an atomic
11- //! and using relaxed ordering to load it. This means that calling it will be no
12- //! more expensive then calling any other dynamically imported function.
10+ //! This is implemented simply by storing a function pointer in an atomic.
11+ //! Loading and calling this function will have little or no overhead
12+ //! compared with calling any other dynamically imported function.
1313//!
1414//! The stored function pointer starts out as an importer function which will
1515//! swap itself with the real function when it's called for the first time. If
1616//! the real function can't be imported then a fallback function is used in its
17- //! place. While this is zero cost for the happy path (where the function is
17+ //! place. While this is low cost for the happy path (where the function is
1818//! already loaded) it does mean there's some overhead the first time the
1919//! function is called. In the worst case, multiple threads may all end up
2020//! importing the same function unnecessarily.
@@ -175,7 +175,7 @@ pub mod WaitOnAddress {
175175
176176 #[ inline( always) ]
177177 pub fn option ( ) -> Option < F > {
178- let f = WAIT_ON_ADDRESS . load ( Ordering :: Relaxed ) ;
178+ let f = WAIT_ON_ADDRESS . load ( Ordering :: Acquire ) ;
179179 if !f. is_null ( ) { Some ( unsafe { mem:: transmute ( f) } ) } else { try_load ( ) }
180180 }
181181
@@ -185,7 +185,7 @@ pub mod WaitOnAddress {
185185 // load the module
186186 let mut wait_on_address = None ;
187187 if let Some ( func) = try_load_inner ( ) {
188- WAIT_ON_ADDRESS . store ( func. as_ptr ( ) , Ordering :: Relaxed ) ;
188+ WAIT_ON_ADDRESS . store ( func. as_ptr ( ) , Ordering :: Release ) ;
189189 wait_on_address = Some ( unsafe { mem:: transmute ( func) } ) ;
190190 }
191191 // Don't try to load the module again even if loading failed.
0 commit comments