use super::FiberId;
pub(crate) fn csw_lua(id: Option<FiberId>) -> Option<u64> {
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(id)
local f
if id == nil then
f = fiber.self()
id = f.id()
else
f = fiber.find(id)
end
if f == nil then
return nil
end
if f.csw ~= nil then
return f:csw()
else
return fiber.info({bt = false})[id].csw
end
end
"#).unwrap();
unsafe {
FUNCTION_DEFINED = true;
}
}
lua.get::<crate::tlua::LuaFunction<_>, _>("fiber_csw")
.unwrap()
.into_call_with_args(id)
.unwrap()
}
pub fn check_yield<F, T>(f: F) -> YieldResult<T>
where
F: FnOnce() -> T,
{
let csw_before = crate::fiber::csw();
let res = f();
if crate::fiber::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_accurate();
let _ = crate::fiber::csw();
let elapsed = now.elapsed();
print!("{elapsed:?} ");
assert!(elapsed < Duration::from_millis(1));
}
}