@@ -121,6 +121,10 @@ pub fn on_hotpatch(f: impl Fn() + Send + Sync + 'static) {
121121 internal:: on_hotpatch ( f)
122122}
123123
124+ pub fn is_stale ( ) -> bool {
125+ internal:: is_stale ( )
126+ }
127+
124128#[ cfg( all( feature = "enable" , not( target_arch = "wasm32" ) ) ) ]
125129mod internal {
126130 use crate :: core:: theme;
@@ -136,8 +140,16 @@ mod internal {
136140 use beacon:: span;
137141 use beacon:: span:: present;
138142
143+ use std:: collections:: BTreeSet ;
139144 use std:: sync:: atomic:: { self , AtomicBool , AtomicUsize } ;
140- use std:: sync:: { Arc , LazyLock , RwLock } ;
145+ use std:: sync:: { Arc , LazyLock , Mutex , OnceLock , RwLock } ;
146+
147+ static IS_STALE : AtomicBool = AtomicBool :: new ( false ) ;
148+
149+ static HOT_FUNCTIONS_PENDING : Mutex < BTreeSet < u64 > > =
150+ Mutex :: new ( BTreeSet :: new ( ) ) ;
151+
152+ static HOT_FUNCTIONS : OnceLock < BTreeSet < u64 > > = OnceLock :: new ( ) ;
141153
142154 pub fn init ( metadata : Metadata ) {
143155 let name = metadata. name . split ( "::" ) . next ( ) . unwrap_or ( metadata. name ) ;
@@ -150,6 +162,20 @@ mod internal {
150162 } ;
151163
152164 cargo_hot:: connect ( ) ;
165+
166+ cargo_hot:: subsecond:: register_handler ( Arc :: new ( || {
167+ if HOT_FUNCTIONS . get ( ) . is_none ( ) {
168+ HOT_FUNCTIONS
169+ . set ( std:: mem:: take (
170+ & mut HOT_FUNCTIONS_PENDING
171+ . lock ( )
172+ . expect ( "Lock hot functions" ) ,
173+ ) )
174+ . expect ( "Set hot functions" ) ;
175+ }
176+
177+ IS_STALE . store ( false , atomic:: Ordering :: Relaxed ) ;
178+ } ) ) ;
153179 }
154180
155181 pub fn quit ( ) -> bool {
@@ -286,15 +312,34 @@ mod internal {
286312
287313 // The `move` here is important. Hotpatching will not work
288314 // otherwise.
289- cargo_hot:: subsecond:: call ( move || {
315+ let mut f = cargo_hot:: subsecond:: HotFn :: current ( move || {
290316 f. take ( ) . expect ( "Hot function is stale" ) ( )
291- } )
317+ } ) ;
318+
319+ let address = f. ptr_address ( ) . 0 ;
320+
321+ if let Some ( hot_functions) = HOT_FUNCTIONS . get ( ) {
322+ if hot_functions. contains ( & address) {
323+ IS_STALE . store ( true , atomic:: Ordering :: Relaxed ) ;
324+ }
325+ } else {
326+ let _ = HOT_FUNCTIONS_PENDING
327+ . lock ( )
328+ . expect ( "Lock hot functions" )
329+ . insert ( address) ;
330+ }
331+
332+ f. call ( ( ) )
292333 }
293334
294335 pub fn on_hotpatch ( f : impl Fn ( ) + Send + Sync + ' static ) {
295336 cargo_hot:: subsecond:: register_handler ( Arc :: new ( f) ) ;
296337 }
297338
339+ pub fn is_stale ( ) -> bool {
340+ IS_STALE . load ( atomic:: Ordering :: Relaxed )
341+ }
342+
298343 fn span ( span : span:: Stage ) -> Span {
299344 log ( client:: Event :: SpanStarted ( span. clone ( ) ) ) ;
300345
@@ -428,4 +473,8 @@ mod internal {
428473 }
429474
430475 pub fn on_hotpatch ( _f : impl Fn ( ) + Send + Sync + ' static ) { }
476+
477+ pub fn is_stale ( ) -> bool {
478+ false
479+ }
431480}
0 commit comments