lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]

Leo Razoumov wrote:
> C functionality I need is already inside a C library, but in order to
> calculate a quadrature (definite integral) the C function takes a
> callback which is a wrapper around a Lua function. Call chain becomes
> essentially Lua->C->Lua and one of the Lua functions is inside a tight
> loop.
> [...]
> I am probably asking for too much, but is it possible to call into Lua
> without explicit stack manipulations at least for some simple calling
> conventions?

I haven't mentioned one rather strange way out of this: perform
inversion of control by switching C stacks.

So the legacy C library (offering the push-style API) and your Lua
code would get separate C stacks in the same process/thread. Then
both of them run in two tight loops:

Legacy C code:

  for (;;) {
    y = eval_func(x);

Lua code:

  local x = next_x()
  while x do
    local y = f(x)  -- Evaluate the target function
    x = next_x(y)   -- Pass back result and get the next x

It works like this: eval_point() switches C stacks and _returns_
its argument to the next_x() iterator. The Lua loop continues with
the new 'x', evaluates the target function and passes 'y' as an
argument to the iterator. The iterator switches back to the other
C stack and _returns_ 'y' to the caller of eval_point().

This is a bit like Lua coroutines work, where the iterator yields
and eval_func() resumes. Except that we're switching C stacks, not
Lua stacks.

You could implement something like this right now, even without
any changes to LuaJIT. You'll just have to grab one of the
lightweight C coroutine libraries and add the required plumbing.

It may be a little odd to wrap your head around it, but the
performance ought to be pretty good. C stack switching can be done
with a couple of instructions (but avoid swapcontext or GNU Pth at
all cost). The JIT compiler can keep all of the state in the tight
loop and will do its best at optimizing it.