Coco changes the semantics of several standard API functions and provides a few API extensions for Lua.
By default all your coroutines get an associated C stack. If you want to be more selective, see below.
Lua API extensions
All coroutine.* functions should be fully upwards compatible.
coroutine.coco
This field is true when Coco is present (nil otherwise).
coro = coroutine.create(f [, cstacksize])
func = coroutine.wrap(f [, cstacksize])
The optional argument cstacksize specifies the size of the C stack to allocate for the coroutine:
- A default stack size is used if cstacksize is not given or is nil or zero.
- No C stack is allocated if cstacksize is -1.
- Any other value is rounded up to the minimum size (i.e. use 1 to get the minimum size).
Important notice for LuaJIT: JIT compiled functions cannot yield if a coroutine does not have a dedicated C stack.
olddefault = coroutine.cstacksize([newdefault])
Returns the current default C stack size (may be 0 if the underlying context switch method has its own default). Sets a new default C stack size if newdefault is present. Use 0 to reset it to the default C stack size. Any other value is rounded up to the minimum size.
C API extensions
All C API functions are either unchanged or upwards compatible.
int lua_yield(lua_State *L, int nresults)
The semantics for lua_yield() have changed slightly. Existing programs should work fine as long as they follow the usage conventions from the Lua manual:
return lua_yield(L, nresults);
Previously lua_yield() returned a 'magic' value (-1) that indicated a yield. Your C function had to pass this value on to the Lua core and was not called again.
Now, if the current coroutine has an associated C stack, lua_yield() returns the number of arguments passed back from the resume. This just happens to be the right convention for returning them as a result from a C function. I.e. if you used the above convention, you'll never notice the change.
But the results are on the Lua stack when lua_yield() returns. So the C function can just continue and process them or retry an I/O operation etc. And your whole C stack frame (local variables etc.) is still there, too. You can yield from anywhere in your C program, even several call levels deeper.
Of course all of this only works with Lua+Coco and not with standard Lua.
lua_State *lua_newcthread(lua_State *L, int cstacksize)
This is an (optional) new function that allows you to create a coroutine with an associated C stack directly from the C API. Other than that it works the same as lua_newthread(L).
You have to declare this function as extern yourself, since it's not part of the official Lua API. This means that a C module that uses this call cannot be loaded with standard Lua. This may be intentional.
If you want your C module to work with both standard Lua and Lua+Coco you can check whether Coco is available with:
lua_getfield(L, LUA_GLOBALSINDEX, "coroutine"); lua_getfield(L, -1, "coco"); coco_available = lua_toboolean(L, -1); lua_pop(L, 2);
You can create coroutines with a C stack by calling the Lua function coroutine.create() from C, too.