Fiber based coroutines for Lua 5.0.2 on Win32

  — Wim Couwenberg, August 6, 2005

This extension library “fiber” offers functionality equivalent to the coroutine package in Lua 5.0.2. It runs with the vanilla Lua 5.0.2 distribution and needs no additional patches to the Lua core. The equivalents of coroutines in the coroutine package are called fibers in the fiber package. The main difference between a coroutine and a fiber is that a running fiber can be suspended anywhere in a call chain, regardless of its C and Lua call stack nesting levels. This is possible because each fiber has both a separate Lua stack and a separate C stack to execute its code. Note however that all fibers created in a Lua state still run in a single system thread. Thus fibers avoid the many pitfalls of full-blown preemptive threads. The fiber package is based on Win32 fibers, available since Windows 98. You can read about Win32 fibers here. Here's a simple example that cannot be achieved with coroutines (since coroutine.yield is a C function):

> f = fiber.create(fiber.yield)
> = fiber.resume(f, "hello world!")
true  hello world!

Caveats

The fiber package was created as an experiment to see if Win32 fibers could cut it as an alternative to Lua coroutines. Though I did develop it as a reliable package, I never seriously used it in any “industrial strength” Lua application. Since Lua 5.0.2 garbage collection is designed to run atomically, it is a very bad idea to yield from a __gc metamethod, either directly or indirectly. The fiber package doesn't prevent you from doing so however, so be extra careful. I never tested the fiber package in any kind of “hairy” situation, like yielding from hook functions or metamethods etc. If you encounter some unexpected behaviour please let me know and I'll at least give it some thought. While developing the package in Borland CBuilder 6 I noticed —much to my annoyance again— that running the fiber package inside the IDE (both with or without debug info) leads to completely erratic behaviour. From the command line everything runs smoothly.

The fiber interface

The fiber package follows the same interface as the standard coroutine package.

fiber.create(startfunction)
fiber.resume(fiber [, arguments])
fiber.yield(results)
fiber.status(fiber)
The fiber.create call returns a new fiber. It takes a start function for the new fiber as its single argument. The new fiber is suspended just before execution of the start function. With fiber.resume you can resume a suspended fiber. It takes the fiber to resume as its first argument. Any further arguments are passed to the resumed fiber either as arguments for its start function (if a fiber is resumed for the first time) or as return values for the fiber.yield call that suspended the fiber. If the fiber.resume call fails it returns false and an error message. If it succeeds it returns true followed by all values resulting form either a return statement or a fiber.yield call in the resumed fiber. Call fiber.yield to suspend the active fiber. You cannot yield form the main fiber (that was never explicitly created or resumed in the first place). All arguments to fiber.yield are passed back to the fiber.resume call that resumed the fiber. You can obtain a fiber's status by passing it to the fiber.status function. The status is one of the strings “suspended”, “dead”, “running” or “normal”.

The C API

Install the package in an existing Lua state with a call to luaopen_fiber. This initialises Win32 fiber support for the calling thread and then installs the fiber interface in a global “fiber” table in the Lua state. Note that the Lua state must henceforth be used only by the same thread that called luaopen_fiber on it for the fiber package to function properly. You can apply additional linkage specifiers for the (single) C API function by defining the LUAFIBER_API symbol appropriately. If you encounter linker errors for the fiber functions declared in windows.h you should probably define the _WIN32_WINNT symbol to a value that is appropriate for your specific platform. More information is available here.

License

The fiber package is distributed under the same liberal license as the Lua distribution itself, which basically means: have a ball! (Just don't blame me afterwards.)