pub fn csw() -> i32 {
static mut FUNCTION_DEFINED: bool = false;
let lua = crate::lua_state();
if unsafe { !FUNCTION_DEFINED } {
#[rustfmt::skip]
lua.exec(r#"
local fiber = require('fiber')
function fiber_csw()
local fiber_self = fiber.self()
if fiber_self.csw ~= nil then
return fiber_self:csw()
else
return fiber.info({bt = false})[fiber.id()].csw
end
end
"#).unwrap();
unsafe {
FUNCTION_DEFINED = true;
}
}
lua.get::<crate::tlua::LuaFunction<_>, _>("fiber_csw")
.unwrap()
.into_call()
.unwrap()
}
pub fn check_yield<F, T>(f: F) -> YieldResult<T>
where
F: FnOnce() -> T,
{
let csw_before = csw();
let res = f();
if csw() == csw_before {
YieldResult::DidntYield(res)
} else {
YieldResult::Yielded(res)
}
}
#[derive(Debug, PartialEq, Eq)]
pub enum YieldResult<T> {
DidntYield(T),
Yielded(T),
}
#[cfg(feature = "internal_test")]
mod tests {
use super::YieldResult;
use crate::fiber;
use std::time::Duration;
#[crate::test(tarantool = "crate")]
fn check_yield() {
assert_eq!(
super::check_yield(|| ()), YieldResult::DidntYield(())
);
assert_eq!(
super::check_yield(|| fiber::sleep(Duration::ZERO)),
YieldResult::Yielded(())
);
}
#[crate::test(tarantool = "crate")]
fn performance() {
let now = crate::time::Instant::now();
let _ = super::csw();
let elapsed = now.elapsed();
print!("{elapsed:?} ");
assert!(elapsed < Duration::from_millis(1));
}
}