@@ -419,7 +419,7 @@ impl Lua {
419
419
// Make sure that Lua is initialized
420
420
let _ = Self :: get_or_init_from_ptr ( state) ;
421
421
422
- callback_error_ext ( state, ptr:: null_mut ( ) , move |extra, nargs| {
422
+ callback_error_ext ( state, ptr:: null_mut ( ) , true , move |extra, nargs| {
423
423
let rawlua = ( * extra) . raw_lua ( ) ;
424
424
let _guard = StateGuard :: new ( rawlua, state) ;
425
425
let args = A :: from_stack_args ( nargs, 1 , None , rawlua) ?;
@@ -652,7 +652,7 @@ impl Lua {
652
652
// We don't support GC interrupts since they cannot survive Lua exceptions
653
653
return ;
654
654
}
655
- let result = callback_error_ext ( state, ptr:: null_mut ( ) , move |extra, _| {
655
+ let result = callback_error_ext ( state, ptr:: null_mut ( ) , false , move |extra, _| {
656
656
let interrupt_cb = ( * extra) . interrupt_callback . clone ( ) ;
657
657
let interrupt_cb = mlua_expect ! ( interrupt_cb, "no interrupt callback set in interrupt_proc" ) ;
658
658
if XRc :: strong_count ( & interrupt_cb) > 2 {
@@ -690,6 +690,60 @@ impl Lua {
690
690
}
691
691
}
692
692
693
+ /// Sets a thread event callback that will be called when a thread is created or destroyed.
694
+ ///
695
+ /// The callback is called with a [`Value`] argument that is either:
696
+ /// - A [`Thread`] object when thread is created
697
+ /// - A [`LightUserData`] when thread is destroyed
698
+ #[ cfg( any( feature = "luau" , doc) ) ]
699
+ #[ cfg_attr( docsrs, doc( cfg( feature = "luau" ) ) ) ]
700
+ pub fn set_thread_event_callback < F > ( & self , callback : F )
701
+ where
702
+ F : Fn ( & Lua , Value ) -> Result < ( ) > + MaybeSend + ' static ,
703
+ {
704
+ unsafe extern "C-unwind" fn userthread_proc ( parent : * mut ffi:: lua_State , child : * mut ffi:: lua_State ) {
705
+ let extra = ExtraData :: get ( child) ;
706
+ let thread_cb = match ( * extra) . userthread_callback {
707
+ Some ( ref cb) => cb. clone ( ) ,
708
+ None => return ,
709
+ } ;
710
+ if XRc :: strong_count ( & thread_cb) > 2 {
711
+ return ; // Don't allow recursion
712
+ }
713
+ let value = match parent. is_null ( ) {
714
+ // Thread is about to be destroyed, pass light userdata
715
+ true => Value :: LightUserData ( crate :: LightUserData ( child as _ ) ) ,
716
+ false => {
717
+ // Thread is created, pass thread object
718
+ ffi:: lua_pushthread ( child) ;
719
+ ffi:: lua_xmove ( child, ( * extra) . ref_thread , 1 ) ;
720
+ Value :: Thread ( Thread ( ( * extra) . raw_lua ( ) . pop_ref_thread ( ) , child) )
721
+ }
722
+ } ;
723
+ callback_error_ext ( ( * extra) . raw_lua ( ) . state ( ) , extra, false , move |extra, _| {
724
+ thread_cb ( ( * extra) . lua ( ) , value)
725
+ } )
726
+ }
727
+
728
+ // Set thread callback
729
+ let lua = self . lock ( ) ;
730
+ unsafe {
731
+ ( * lua. extra . get ( ) ) . userthread_callback = Some ( XRc :: new ( callback) ) ;
732
+ ( * ffi:: lua_callbacks ( lua. main_state ( ) ) ) . userthread = Some ( userthread_proc) ;
733
+ }
734
+ }
735
+
736
+ /// Removes any thread event callback previously set by `set_thread_event_callback`.
737
+ #[ cfg( any( feature = "luau" , doc) ) ]
738
+ #[ cfg_attr( docsrs, doc( cfg( feature = "luau" ) ) ) ]
739
+ pub fn remove_thread_event_callback ( & self ) {
740
+ let lua = self . lock ( ) ;
741
+ unsafe {
742
+ ( * lua. extra . get ( ) ) . userthread_callback = None ;
743
+ ( * ffi:: lua_callbacks ( lua. main_state ( ) ) ) . userthread = None ;
744
+ }
745
+ }
746
+
693
747
/// Sets the warning function to be used by Lua to emit warnings.
694
748
///
695
749
/// Requires `feature = "lua54"`
@@ -705,7 +759,7 @@ impl Lua {
705
759
706
760
unsafe extern "C-unwind" fn warn_proc ( ud : * mut c_void , msg : * const c_char , tocont : c_int ) {
707
761
let extra = ud as * mut ExtraData ;
708
- callback_error_ext ( ( * extra) . raw_lua ( ) . state ( ) , extra, |extra, _| {
762
+ callback_error_ext ( ( * extra) . raw_lua ( ) . state ( ) , extra, false , |extra, _| {
709
763
let warn_callback = ( * extra) . warn_callback . clone ( ) ;
710
764
let warn_callback = mlua_expect ! ( warn_callback, "no warning callback set in warn_proc" ) ;
711
765
if XRc :: strong_count ( & warn_callback) > 2 {
@@ -1444,7 +1498,7 @@ impl Lua {
1444
1498
Err ( _) => return ,
1445
1499
} ,
1446
1500
ffi:: LUA_TTHREAD => {
1447
- ffi:: lua_newthread ( state) ;
1501
+ ffi:: lua_pushthread ( state) ;
1448
1502
}
1449
1503
#[ cfg( feature = "luau" ) ]
1450
1504
ffi:: LUA_TBUFFER => {
0 commit comments