@@ -419,7 +419,7 @@ impl Lua {
419419 // Make sure that Lua is initialized
420420 let _ = Self :: get_or_init_from_ptr ( state) ;
421421
422- callback_error_ext ( state, ptr:: null_mut ( ) , move |extra, nargs| {
422+ callback_error_ext ( state, ptr:: null_mut ( ) , true , move |extra, nargs| {
423423 let rawlua = ( * extra) . raw_lua ( ) ;
424424 let _guard = StateGuard :: new ( rawlua, state) ;
425425 let args = A :: from_stack_args ( nargs, 1 , None , rawlua) ?;
@@ -652,7 +652,7 @@ impl Lua {
652652 // We don't support GC interrupts since they cannot survive Lua exceptions
653653 return ;
654654 }
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, _| {
656656 let interrupt_cb = ( * extra) . interrupt_callback . clone ( ) ;
657657 let interrupt_cb = mlua_expect ! ( interrupt_cb, "no interrupt callback set in interrupt_proc" ) ;
658658 if XRc :: strong_count ( & interrupt_cb) > 2 {
@@ -690,6 +690,60 @@ impl Lua {
690690 }
691691 }
692692
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+
693747 /// Sets the warning function to be used by Lua to emit warnings.
694748 ///
695749 /// Requires `feature = "lua54"`
@@ -705,7 +759,7 @@ impl Lua {
705759
706760 unsafe extern "C-unwind" fn warn_proc ( ud : * mut c_void , msg : * const c_char , tocont : c_int ) {
707761 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, _| {
709763 let warn_callback = ( * extra) . warn_callback . clone ( ) ;
710764 let warn_callback = mlua_expect ! ( warn_callback, "no warning callback set in warn_proc" ) ;
711765 if XRc :: strong_count ( & warn_callback) > 2 {
@@ -1444,7 +1498,7 @@ impl Lua {
14441498 Err ( _) => return ,
14451499 } ,
14461500 ffi:: LUA_TTHREAD => {
1447- ffi:: lua_newthread ( state) ;
1501+ ffi:: lua_pushthread ( state) ;
14481502 }
14491503 #[ cfg( feature = "luau" ) ]
14501504 ffi:: LUA_TBUFFER => {
0 commit comments