lua-users home
lua-l archive

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


The list already contains a few discussions about yielding across a C
boundary in general, and across pcall() in particular, but I have an
additional complication to add to the discussion: I am building Lua as
C++.

My searching has turned up two approaches to the
yield-across-C-boundary problem:

* Eric Jacobs' coroutines power patch, which introduces lua_call_yp()
and requires yieldable C functions to be written so that they can save
their state and resume themselves later if required, and

* Mike Pall's Coco, using swapcontext() or other OS API calls to
generate genuine coroutines in C.

However, I'm not sure which (if either) approach is correct for me.

The coroutines power patch is written for 5.0.2, so it would take a
bit of work to port to 5.1.  Worse, pcall() does not seem to be
adapted, and as I see it, adding pcall() support to the power patch is
a much bigger challenge than the 5.0.2=>5.1 port.  I have an idea on
how it might be done, but would like to hear the current state of
affairs for this patch before I reinvent the wheel.

Despite the version problems, this patch has the advantage of avoiding
any OS-specific calls.  This would seem to improve portability.

Coco is intriguing and looks fantastic for C, but for C++, problems
arise.  The big question mark is for try/catch handling.  One
coroutine may have a try/catch block active, but will swapping this
coroutine in and out adjust the exception handler appropriately?  My
question is not "will this work?", as this is easy enough to test for
any given platform, but rather "should this work?"

Coco uses different C-stack-swapping strategies based on platform and
compile-time #defines.  Of the four strategies listed, only the
Windows API clearly documents its behavior (and happily, Windows
fibers do properly handle exceptions).  But for Unix, my inability to
find a clear specification makes me fear portable C++ coroutines may
be impossible to write.

POSIX's ucontext interfaces seem completely unspecified with regard to
C++ behavior.  It's a set of C functions, so this isn't totally
surprising.  Coco can also use setjmp/longjmp to implement coroutines
by modifying the platform-specific contents of jmp_buf, but that makes
me very nervous indeed.

Using setjmp/longjmp for Lua errors in C++ is not a solution. 
Try/catch, unlike setjmp/longjmp, ensures that objects are properly
destructed as the stack is unwound.  Avoiding try/catch is only a
suitable solution so long as no C++ objects are used within Lua C
functions, but that defeats the purpose of compiling Lua as C++ in the
first place.

Yeilding across a pcall() is something I will eventually need.  Here
are my questions for the list:

1) Has anybody faced the same problem as me?  (pcall/yield/C++)? 
Insights on this would be greatly appreciated.

2) Is the Wiki up to date on the coroutines power patch?  Has anyone
done work on a 5.1 port, or on pcall() support?

3) Can anyone enlighten me on ucontext/swapcontext behavior in the
presence of C++ exception handling?  Is there some POSIX document that
specifies this that I have missed?  Or is swapcontext really unusable
in portable C++?

4) Are there any other practical approaches to the yield-across-C
problem that I have missed?

Thanks,
Greg F