lua-users home
lua-l archive

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


> Could you be a little bit more specific?  Just some functions to save/set
> L->stack & co and a registration for lock-callbacks on table-set/get?
> Or something more sophisticated?  What about the GC?

We broke the lua_State in two structs; the lua_State itself has the 
thread-specific data, and it points to the other structure with the 
"global" data. There is only one new function (let us call it lua_newstack, 
we don't know the final name): the call lua_newstack(L, stacksize) returns 
a new lua_State sharing the global state with L. Actually, lua_open is now 
a macro lua_newstack(NULL, stacksize).

All stacks sharing the same global part are in a linked list, so the GC
traverse them all.

lua_close destroys a stack. If it is the last stack of the global state,
it also closes the global state.

About the locks: we considered the whole core of Lua as one single critical 
region (it is too complicated and too expensive to lock every single 
internal operation that can have impact in other threads). So all API 
functions have a pair of macros LUA_LOCK/LUA_UNLOCK around them. On the 
other side, whenever Lua calls C, in unlocks its core. So, unless you are 
in a closed loop completely inside Lua, you have plenty of opportunites to 
switch treads. (Notice that the core never blocks; all blocking functions 
are C functions outside). If you really want it badly, you can register an 
empty line-hook (because line-hooks are outside the core, everytime Lua 
calls the line-hook it will unlock and lock again). 

The following code shows the critical parts for implementing multi-threads
(with pthreads) in Lua 4.1. An implementation with co-routines could
follow the same structure, but without the macros for lock/unlock.


file p.h (included in lua.h)

  #include <pthread.h>

  #define LUA_LOCK	pthread_mutex_lock(&mutex)
  #define LUA_UNLOCK	pthread_mutex_unlock(&mutex)

  /* mutex for the Lua core */
  extern pthread_mutex_t mutex;

  ...


file p.c

  #include <pthread.h>

  #include "../lua.h"
  #include "../lauxlib.h"

  pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

  static void *init_thread (void *arg) {
    lua_State *L = (lua_State *)arg;
    int n = lua_getn(L, 1);  /* number of arguments */
    int i;
    for (i=1; i<=n; i++)  /* push arguments */
      lua_rawgeti(L, 1, i);
    lua_remove(L, 1);  /* table is garbage now */
    pthread_detach(pthread_self());
    lua_call(L, n, 0);
    return NULL;
  }


  static int newthread (lua_State *L) {
    lua_State *NL;
    int ref;
    pthread_t thread;
    luaL_checktype(L, 1, LUA_TFUNCTION);
    luaL_checktype(L, 2, LUA_TTABLE);
    NL = lua_newstack(L, luaL_opt_int(L, 3, 0));
    if (NL == NULL)
      lua_error(L, "cannot create new stack");
    lua_settop(L, 2);  /* remove eventual stacksize */
    /* move table and function from L to NL */
    ref = lua_ref(L, 1);  /* maybe we need a function for that? */
    lua_getref(NL, ref);
    lua_unref(L, ref);  
    ref = lua_ref(L, 1);
    lua_getref(NL, ref);
    lua_unref(L, ref);  
    if (pthread_create(&thread, NULL, init_thread, NL) != 0)
      lua_error(L, "cannot create new thread");
    return 0;
  }

  ...

-- Roberto