Refactor luaffi proc-macro
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
__internal::{display, type_id},
|
||||
Cdef, CdefBuilder, FfiReturnConvention, IntoFfi, Metatype, MetatypeBuilder, Type, TypeBuilder,
|
||||
Cdef, CdefBuilder, IntoFfi, Metatype, MetatypeBuilder, Type, TypeBuilder, TypeType,
|
||||
UnsafeExternCFn,
|
||||
};
|
||||
use luaify::luaify;
|
||||
@@ -43,7 +43,7 @@ pub struct lua_future<F: Future<Output: IntoFfi>> {
|
||||
sig: Signature,
|
||||
poll: fn(Pin<&mut Self>, cx: &mut Context) -> Poll<()>,
|
||||
state: State<F>,
|
||||
take: unsafe extern "C" fn(&mut Self) -> <F::Output as IntoFfi>::To,
|
||||
take: unsafe extern "C" fn(&mut Self) -> <F::Output as IntoFfi>::Into,
|
||||
drop: unsafe extern "C" fn(&mut Self),
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ impl<F: Future<Output: IntoFfi>> lua_future<F> {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe extern "C" fn take(&mut self) -> <F::Output as IntoFfi>::To {
|
||||
unsafe extern "C" fn take(&mut self) -> <F::Output as IntoFfi>::Into {
|
||||
// `fut:__take()` returns the fulfilled value by-value (not by out-param) because if we
|
||||
// preallocate a cdata for the out-param and the thread for some reason gets dropped and
|
||||
// never resumed, the GC could call the destructor on an uninitialised cdata.
|
||||
@@ -136,8 +136,12 @@ unsafe impl<F: Future<Output: IntoFfi> + 'static> Type for lua_future<F> {
|
||||
display!("future__{:x}", type_id::<F>())
|
||||
}
|
||||
|
||||
fn ty() -> TypeType {
|
||||
TypeType::Aggregate
|
||||
}
|
||||
|
||||
fn cdecl(name: impl Display) -> impl Display {
|
||||
display!("struct future__{:x} {name}", type_id::<F>())
|
||||
display!("struct {} {name}", Self::name())
|
||||
}
|
||||
|
||||
fn build(s: &mut TypeBuilder) {
|
||||
@@ -148,7 +152,7 @@ unsafe impl<F: Future<Output: IntoFfi> + 'static> Type for lua_future<F> {
|
||||
unsafe impl<F: Future<Output: IntoFfi> + 'static> Cdef for lua_future<F> {
|
||||
fn build(s: &mut CdefBuilder) {
|
||||
s.field_opaque(mem::offset_of!(Self, take)) // opaque .sig, .poll and .state
|
||||
.field::<UnsafeExternCFn<(&mut Self,), <F::Output as IntoFfi>::To>>("__take")
|
||||
.field::<UnsafeExternCFn<(&mut Self,), <F::Output as IntoFfi>::Into>>("__take")
|
||||
.field::<UnsafeExternCFn<(&mut Self,), ()>>("__drop");
|
||||
}
|
||||
}
|
||||
@@ -162,24 +166,25 @@ unsafe impl<F: Future<Output: IntoFfi> + 'static> Metatype for lua_future<F> {
|
||||
}
|
||||
|
||||
unsafe impl<F: Future<Output: IntoFfi> + 'static> IntoFfi for lua_future<F> {
|
||||
type To = lua_future<F>;
|
||||
type Into = lua_future<F>;
|
||||
|
||||
fn convert(self) -> Self::To {
|
||||
fn convert(self) -> Self::Into {
|
||||
self
|
||||
}
|
||||
|
||||
fn postlude(ret: &str, _conv: FfiReturnConvention) -> impl Display {
|
||||
fn postlude(ret: &str) -> impl Display {
|
||||
// When returning a future from Rust to Lua, yield it immediately to the runtime which will
|
||||
// poll it to completion in the background, then take the fulfilled value once the thread
|
||||
// gets resumed. Lua user code should never to worry about awaiting futures.
|
||||
//
|
||||
// Once the current thread gets resumed and we take the future's fulfilled value, we clear
|
||||
// the finaliser on the future and forget it (there is nothing to call drop on).
|
||||
// the finaliser on the future and forget it (there is nothing to drop once the value is
|
||||
// taken).
|
||||
//
|
||||
// `coroutine.yield` is cached as `yield` and `ffi.gc` as `gc` in locals (see lib.rs)
|
||||
// `coroutine.yield` is cached as `__yield` and `ffi.gc` as `__gc` in locals (see lib.rs)
|
||||
display!(
|
||||
"yield({ret}); {ret} = gc({ret}, nil):__take(); {}",
|
||||
<F::Output as IntoFfi>::postlude(ret, FfiReturnConvention::ByValue)
|
||||
"__yield({ret}); {ret} = __gc({ret}, nil):__take(); {}",
|
||||
<F::Output as IntoFfi>::postlude(ret)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user