Skip to content

Commit cb239bb

Browse files
committed
feat(fiber): implement deferred fibers without yields
Current implementations uses the lua runtime to achieve this goal. This is necessary due to the limitation of tarantool ffi api. We are planning to fix this in the future by adding a single function to tarantool api.
1 parent 6179efe commit cb239bb

File tree

6 files changed

+333
-28
lines changed

6 files changed

+333
-28
lines changed

hlua/hlua/src/lib.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,9 +125,12 @@ pub use lua_tables::LuaTable;
125125
pub use lua_tables::LuaTableIterator;
126126
pub use tuples::TuplePushError;
127127
pub use userdata::UserdataOnStack;
128-
pub use userdata::{push_userdata, read_userdata};
128+
pub use userdata::{push_userdata, read_userdata, push_some_userdata};
129129
pub use values::StringInLua;
130130

131+
// Needed for `lua_error` macro
132+
pub use ffi::luaL_error;
133+
131134
mod any;
132135
mod functions_write;
133136
mod lua_functions;

hlua/hlua/src/macros.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,21 @@ macro_rules! implement_lua_read {
6060
}
6161
};
6262
}
63+
64+
#[macro_export]
65+
macro_rules! c_ptr {
66+
($s:literal) => {
67+
::std::concat!($s, "\0").as_bytes().as_ptr() as *mut i8
68+
};
69+
}
70+
71+
#[macro_export]
72+
macro_rules! lua_error {
73+
($l:expr, $msg:literal) => {
74+
{
75+
$crate::luaL_error($l, c_ptr!($msg));
76+
unreachable!()
77+
}
78+
}
79+
}
80+

hlua/hlua/src/userdata.rs

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,45 @@ use crate::{
1313
LuaRead,
1414
InsideCallback,
1515
LuaTable,
16+
c_ptr,
1617
};
1718

19+
/// Pushes `value` of type `T` onto the stack as a userdata. The value is
20+
/// put inside a `Option` so that it can be safely moved out of there. Useful
21+
/// for example when passing `FnOnce` as a c closure, because it must be dropped
22+
/// after the call.
23+
/// *[0, +1, -]*
24+
pub unsafe fn push_some_userdata<T>(lua: *mut ffi::lua_State, value: T) {
25+
type UDBox<T> = Option<T>;
26+
let ud_ptr = ffi::lua_newuserdata(lua, std::mem::size_of::<UDBox<T>>());
27+
std::ptr::write(ud_ptr as *mut UDBox<T>, Some(value));
28+
29+
if std::mem::needs_drop::<T>() {
30+
// Creating a metatable.
31+
ffi::lua_newtable(lua);
32+
33+
// Index "__gc" in the metatable calls the object's destructor.
34+
ffi::lua_pushstring(lua, c_ptr!("__gc"));
35+
ffi::lua_pushcfunction(lua, wrap_gc::<T>);
36+
ffi::lua_settable(lua, -3);
37+
38+
ffi::lua_setmetatable(lua, -2);
39+
}
40+
41+
/// A callback for the "__gc" event. It checks if the value was moved out
42+
/// and if not it drops the value.
43+
unsafe extern "C" fn wrap_gc<T>(lua: *mut ffi::lua_State) -> i32 {
44+
let ud_ptr = ffi::lua_touserdata(lua, 1);
45+
let ud = (ud_ptr as *mut UDBox<T>)
46+
.as_mut()
47+
.expect("__gc called with userdata pointing to NULL");
48+
drop(ud.take());
49+
50+
0
51+
}
52+
}
53+
54+
1855
// Called when an object inside Lua is being dropped.
1956
#[inline]
2057
extern "C" fn destructor_wrapper<T>(lua: *mut ffi::lua_State) -> libc::c_int {

tarantool/src/error.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rmp::decode::{MarkerReadError, NumValueReadError, ValueReadError};
2626
use rmp::encode::ValueWriteError;
2727

2828
use crate::ffi::tarantool as ffi;
29+
use crate::hlua::LuaError;
2930

3031
/// A specialized [`Result`] type for the crate
3132
pub type Result<T> = std::result::Result<T, Error>;
@@ -71,6 +72,9 @@ pub enum Error {
7172
#[cfg(feature = "net_box")]
7273
#[fail(display = "Sever respond with error: {}", _0)]
7374
Remote(crate::net_box::ResponseError),
75+
76+
#[fail(display = "Lua error: {}", _0)]
77+
LuaError(LuaError),
7478
}
7579

7680
impl From<io::Error> for Error {
@@ -142,6 +146,12 @@ impl From<crate::net_box::ResponseError> for Error {
142146
}
143147
}
144148

149+
impl From<LuaError> for Error {
150+
fn from(error: LuaError) -> Self {
151+
Error::LuaError(error)
152+
}
153+
}
154+
145155
/// Transaction-related error cases
146156
#[derive(Debug, Fail)]
147157
pub enum TransactionError {

0 commit comments

Comments
 (0)