@@ -19,7 +19,8 @@ use crate::string::String;
19
19
use crate :: table:: Table ;
20
20
use crate :: thread:: Thread ;
21
21
use crate :: types:: {
22
- Callback , HookCallback , Integer , LightUserData , LuaRef , MaybeSend , Number , RegistryKey ,
22
+ Callback , CallbackUpvalue , HookCallback , Integer , LightUserData , LuaRef , MaybeSend , Number ,
23
+ RegistryKey ,
23
24
} ;
24
25
use crate :: userdata:: {
25
26
AnyUserData , MetaMethod , UserData , UserDataCell , UserDataFields , UserDataMethods ,
@@ -38,7 +39,7 @@ use std::rc::Rc;
38
39
39
40
#[ cfg( feature = "async" ) ]
40
41
use {
41
- crate :: types:: AsyncCallback ,
42
+ crate :: types:: { AsyncCallback , AsyncCallbackUpvalue , AsyncPollUpvalue } ,
42
43
futures_core:: {
43
44
future:: { Future , LocalBoxFuture } ,
44
45
task:: { Context , Poll , Waker } ,
@@ -396,12 +397,13 @@ impl Lua {
396
397
// to prevent them from being garbage collected.
397
398
398
399
init_gc_metatable_for:: <Callback >( state, None ) ?;
399
- init_gc_metatable_for:: <Lua >( state, None ) ?;
400
+ init_gc_metatable_for:: <CallbackUpvalue >( state, None ) ?;
400
401
init_gc_metatable_for:: <Weak <Mutex <ExtraData >>>( state, None ) ?;
401
402
#[ cfg( feature = "async" ) ]
402
403
{
403
404
init_gc_metatable_for:: <AsyncCallback >( state, None ) ?;
404
- init_gc_metatable_for:: <LocalBoxFuture <Result <MultiValue >>>( state, None ) ?;
405
+ init_gc_metatable_for:: <AsyncCallbackUpvalue >( state, None ) ?;
406
+ init_gc_metatable_for:: <AsyncPollUpvalue >( state, None ) ?;
405
407
init_gc_metatable_for:: <Option <Waker >>( state, None ) ?;
406
408
407
409
// Create empty Waker slot
@@ -1777,22 +1779,22 @@ impl Lua {
1777
1779
' lua : ' callback ,
1778
1780
{
1779
1781
unsafe extern "C" fn call_callback ( state : * mut ffi:: lua_State ) -> c_int {
1780
- callback_error2 ( state, |nargs| {
1781
- let upvalue_idx1 = ffi:: lua_upvalueindex ( 1 ) ;
1782
- let upvalue_idx2 = ffi:: lua_upvalueindex ( 2 ) ;
1783
- if ffi:: lua_type ( state, upvalue_idx1) == ffi:: LUA_TNIL
1784
- || ffi:: lua_type ( state, upvalue_idx2) == ffi:: LUA_TNIL
1785
- {
1782
+ let get_extra = |state| {
1783
+ let upvalue = get_userdata :: < CallbackUpvalue > ( state, ffi:: lua_upvalueindex ( 1 ) ) ;
1784
+ ( * upvalue) . lua . extra . clone ( )
1785
+ } ;
1786
+ callback_error_ext ( state, get_extra, |nargs| {
1787
+ let upvalue_idx = ffi:: lua_upvalueindex ( 1 ) ;
1788
+ if ffi:: lua_type ( state, upvalue_idx) == ffi:: LUA_TNIL {
1786
1789
return Err ( Error :: CallbackDestructed ) ;
1787
1790
}
1788
- let func = get_userdata :: < Callback > ( state, upvalue_idx1) ;
1789
- let lua = get_userdata :: < Lua > ( state, upvalue_idx2) ;
1791
+ let upvalue = get_userdata :: < CallbackUpvalue > ( state, upvalue_idx) ;
1790
1792
1791
1793
if nargs < ffi:: LUA_MINSTACK {
1792
1794
check_stack ( state, ffi:: LUA_MINSTACK - nargs) ?;
1793
1795
}
1794
1796
1795
- let lua = & mut * lua;
1797
+ let lua = & mut ( * upvalue ) . lua ;
1796
1798
lua. state = state;
1797
1799
1798
1800
let mut args = MultiValue :: new ( ) ;
@@ -1801,7 +1803,7 @@ impl Lua {
1801
1803
args. push_front ( lua. pop_value ( ) ) ;
1802
1804
}
1803
1805
1804
- let results = ( * func) ( lua, args) ?;
1806
+ let results = ( ( * upvalue ) . func ) ( lua, args) ?;
1805
1807
let nresults = results. len ( ) as c_int ;
1806
1808
1807
1809
check_stack ( state, nresults) ?;
@@ -1815,12 +1817,13 @@ impl Lua {
1815
1817
1816
1818
unsafe {
1817
1819
let _sg = StackGuard :: new ( self . state ) ;
1818
- check_stack ( self . state , 5 ) ?;
1820
+ check_stack ( self . state , 4 ) ?;
1819
1821
1820
- push_gc_userdata :: < Callback > ( self . state , mem:: transmute ( func) ) ?;
1821
- push_gc_userdata ( self . state , self . clone ( ) ) ?;
1822
- protect_lua ( self . state , 2 , 1 , |state| {
1823
- ffi:: lua_pushcclosure ( state, call_callback, 2 ) ;
1822
+ let lua = self . clone ( ) ;
1823
+ let func = mem:: transmute ( func) ;
1824
+ push_gc_userdata ( self . state , CallbackUpvalue { lua, func } ) ?;
1825
+ protect_lua ( self . state , 1 , 1 , |state| {
1826
+ ffi:: lua_pushcclosure ( state, call_callback, 1 ) ;
1824
1827
} ) ?;
1825
1828
1826
1829
Ok ( Function ( self . pop_ref ( ) ) )
@@ -1844,22 +1847,22 @@ impl Lua {
1844
1847
}
1845
1848
1846
1849
unsafe extern "C" fn call_callback ( state : * mut ffi:: lua_State ) -> c_int {
1847
- callback_error2 ( state, |nargs| {
1848
- let upvalue_idx1 = ffi:: lua_upvalueindex ( 1 ) ;
1849
- let upvalue_idx2 = ffi:: lua_upvalueindex ( 2 ) ;
1850
- if ffi:: lua_type ( state, upvalue_idx1) == ffi:: LUA_TNIL
1851
- || ffi:: lua_type ( state, upvalue_idx2) == ffi:: LUA_TNIL
1852
- {
1850
+ let get_extra = |state| {
1851
+ let upvalue = get_userdata :: < AsyncCallbackUpvalue > ( state, ffi:: lua_upvalueindex ( 1 ) ) ;
1852
+ ( * upvalue) . lua . extra . clone ( )
1853
+ } ;
1854
+ callback_error_ext ( state, get_extra, |nargs| {
1855
+ let upvalue_idx = ffi:: lua_upvalueindex ( 1 ) ;
1856
+ if ffi:: lua_type ( state, upvalue_idx) == ffi:: LUA_TNIL {
1853
1857
return Err ( Error :: CallbackDestructed ) ;
1854
1858
}
1855
- let func = get_userdata :: < AsyncCallback > ( state, upvalue_idx1) ;
1856
- let lua = get_userdata :: < Lua > ( state, upvalue_idx2) ;
1859
+ let upvalue = get_userdata :: < AsyncCallbackUpvalue > ( state, upvalue_idx) ;
1857
1860
1858
1861
if nargs < ffi:: LUA_MINSTACK {
1859
1862
check_stack ( state, ffi:: LUA_MINSTACK - nargs) ?;
1860
1863
}
1861
1864
1862
- let lua = & mut * lua;
1865
+ let lua = & mut ( * upvalue ) . lua ;
1863
1866
lua. state = state;
1864
1867
1865
1868
let mut args = MultiValue :: new ( ) ;
@@ -1868,35 +1871,34 @@ impl Lua {
1868
1871
args. push_front ( lua. pop_value ( ) ) ;
1869
1872
}
1870
1873
1871
- let fut = ( * func) ( lua, args) ;
1872
- push_gc_userdata ( state, fut) ?;
1873
- push_gc_userdata ( state, lua. clone ( ) ) ?;
1874
-
1875
- protect_lua ( state, 2 , 1 , |state| {
1876
- ffi:: lua_pushcclosure ( state, poll_future, 2 ) ;
1874
+ let fut = ( ( * upvalue) . func ) ( lua, args) ;
1875
+ let lua = lua. clone ( ) ;
1876
+ push_gc_userdata ( state, AsyncPollUpvalue { lua, fut } ) ?;
1877
+ protect_lua ( state, 1 , 1 , |state| {
1878
+ ffi:: lua_pushcclosure ( state, poll_future, 1 ) ;
1877
1879
} ) ?;
1878
1880
1879
1881
Ok ( 1 )
1880
1882
} )
1881
1883
}
1882
1884
1883
1885
unsafe extern "C" fn poll_future ( state : * mut ffi:: lua_State ) -> c_int {
1884
- callback_error2 ( state, |nargs| {
1885
- let upvalue_idx1 = ffi:: lua_upvalueindex ( 1 ) ;
1886
- let upvalue_idx2 = ffi:: lua_upvalueindex ( 2 ) ;
1887
- if ffi:: lua_type ( state, upvalue_idx1) == ffi:: LUA_TNIL
1888
- || ffi:: lua_type ( state, upvalue_idx2) == ffi:: LUA_TNIL
1889
- {
1886
+ let get_extra = |state| {
1887
+ let upvalue = get_userdata :: < AsyncPollUpvalue > ( state, ffi:: lua_upvalueindex ( 1 ) ) ;
1888
+ ( * upvalue) . lua . extra . clone ( )
1889
+ } ;
1890
+ callback_error_ext ( state, get_extra, |nargs| {
1891
+ let upvalue_idx = ffi:: lua_upvalueindex ( 1 ) ;
1892
+ if ffi:: lua_type ( state, upvalue_idx) == ffi:: LUA_TNIL {
1890
1893
return Err ( Error :: CallbackDestructed ) ;
1891
1894
}
1892
- let fut = get_userdata :: < LocalBoxFuture < Result < MultiValue > > > ( state, upvalue_idx1) ;
1893
- let lua = get_userdata :: < Lua > ( state, upvalue_idx2) ;
1895
+ let upvalue = get_userdata :: < AsyncPollUpvalue > ( state, upvalue_idx) ;
1894
1896
1895
1897
if nargs < ffi:: LUA_MINSTACK {
1896
1898
check_stack ( state, ffi:: LUA_MINSTACK - nargs) ?;
1897
1899
}
1898
1900
1899
- let lua = & mut * lua;
1901
+ let lua = & mut ( * upvalue ) . lua ;
1900
1902
lua. state = state;
1901
1903
1902
1904
// Try to get an outer poll waker
@@ -1910,7 +1912,8 @@ impl Lua {
1910
1912
1911
1913
let mut ctx = Context :: from_waker ( & waker) ;
1912
1914
1913
- match ( * fut) . as_mut ( ) . poll ( & mut ctx) {
1915
+ let fut = & mut ( * upvalue) . fut ;
1916
+ match fut. as_mut ( ) . poll ( & mut ctx) {
1914
1917
Poll :: Pending => {
1915
1918
check_stack ( state, 1 ) ?;
1916
1919
ffi:: lua_pushboolean ( state, 0 ) ;
@@ -1932,12 +1935,13 @@ impl Lua {
1932
1935
1933
1936
let get_poll = unsafe {
1934
1937
let _sg = StackGuard :: new ( self . state ) ;
1935
- check_stack ( self . state , 5 ) ?;
1938
+ check_stack ( self . state , 4 ) ?;
1936
1939
1937
- push_gc_userdata :: < AsyncCallback > ( self . state , mem:: transmute ( func) ) ?;
1938
- push_gc_userdata ( self . state , self . clone ( ) ) ?;
1939
- protect_lua ( self . state , 2 , 1 , |state| {
1940
- ffi:: lua_pushcclosure ( state, call_callback, 2 ) ;
1940
+ let lua = self . clone ( ) ;
1941
+ let func = mem:: transmute ( func) ;
1942
+ push_gc_userdata ( self . state , AsyncCallbackUpvalue { lua, func } ) ?;
1943
+ protect_lua ( self . state , 1 , 1 , |state| {
1944
+ ffi:: lua_pushcclosure ( state, call_callback, 1 ) ;
1941
1945
} ) ?;
1942
1946
1943
1947
Function ( self . pop_ref ( ) )
@@ -2287,13 +2291,14 @@ impl<'lua, T: AsRef<[u8]> + ?Sized> AsChunk<'lua> for T {
2287
2291
2288
2292
// An optimized version of `callback_error` that does not allocate `WrappedError+Panic` userdata
2289
2293
// and instead reuses unsed and cached values from previous calls (or allocates new).
2290
- // It assumes that ephemeral `Lua` struct is passed as a 2nd upvalue .
2291
- pub unsafe fn callback_error2 < F , R > ( state : * mut ffi:: lua_State , f : F ) -> R
2294
+ // It requires `get_extra` function to return `ExtraData` value .
2295
+ unsafe fn callback_error_ext < E , F , R > ( state : * mut ffi:: lua_State , get_extra : E , f : F ) -> R
2292
2296
where
2297
+ E : Fn ( * mut ffi:: lua_State ) -> Arc < Mutex < ExtraData > > ,
2293
2298
F : FnOnce ( c_int ) -> Result < R > ,
2294
2299
{
2295
- let upvalue_idx2 = ffi:: lua_upvalueindex ( 2 ) ;
2296
- if ffi:: lua_type ( state, upvalue_idx2 ) == ffi:: LUA_TNIL {
2300
+ let upvalue_idx = ffi:: lua_upvalueindex ( 1 ) ;
2301
+ if ffi:: lua_type ( state, upvalue_idx ) == ffi:: LUA_TNIL {
2297
2302
return callback_error ( state, f) ;
2298
2303
}
2299
2304
@@ -2314,9 +2319,9 @@ where
2314
2319
2315
2320
// We cannot shadow Rust errors with Lua ones, so we need to obtain pre-allocated memory
2316
2321
// to store a wrapped error or panic *before* we proceed.
2317
- let lua = get_userdata :: < Lua > ( state, upvalue_idx2 ) ;
2322
+ let extra = get_extra ( state) ;
2318
2323
let prealloc_err = {
2319
- let mut extra = mlua_expect ! ( ( * lua ) . extra. lock( ) , "extra is poisoned" ) ;
2324
+ let mut extra = mlua_expect ! ( extra. lock( ) , "extra is poisoned" ) ;
2320
2325
match extra. prealloc_wrapped_errors . pop ( ) {
2321
2326
Some ( index) => PreallocatedError :: Cached ( index) ,
2322
2327
None => {
@@ -2329,7 +2334,7 @@ where
2329
2334
} ;
2330
2335
2331
2336
let get_prealloc_err = || {
2332
- let mut extra = mlua_expect ! ( ( * lua ) . extra. lock( ) , "extra is poisoned" ) ;
2337
+ let mut extra = mlua_expect ! ( extra. lock( ) , "extra is poisoned" ) ;
2333
2338
match prealloc_err {
2334
2339
PreallocatedError :: New ( ud) => {
2335
2340
ffi:: lua_settop ( state, 1 ) ;
@@ -2350,7 +2355,7 @@ where
2350
2355
match catch_unwind ( AssertUnwindSafe ( || f ( nargs) ) ) {
2351
2356
Ok ( Ok ( r) ) => {
2352
2357
// Return unused WrappedError+Panic to the cache
2353
- let mut extra = mlua_expect ! ( ( * lua ) . extra. lock( ) , "extra is poisoned" ) ;
2358
+ let mut extra = mlua_expect ! ( extra. lock( ) , "extra is poisoned" ) ;
2354
2359
match prealloc_err {
2355
2360
PreallocatedError :: New ( _) if extra. prealloc_wrapped_errors . len ( ) < 16 => {
2356
2361
ffi:: lua_rotate ( state, 1 , -1 ) ;
0 commit comments