lua-users home
lua-l archive

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


Hi,

Jamie Webb wrote:
> No. The lua_newthread() function pushes onto the Lua stack a /Lua value/ 
> representing the thread. This is quite distinct from the the state pointer 
> returned to the C caller.
[...]
> Yes there is. lua_pushlightuserdata(). This light userdata forms the key, and 
> the Lua thread object is the value.

Thank you for your comments. Now I'm understanding your solution.

Ok, so I stand corrected. It can be emulated with two C functions without
changing the public API (but is it GC safe? Ummm ...).

[
Not debating the validity of the solution, but it's a bit contorted to use
a table to lookup a TValue to another TValue where the difference lies
only in the tag (LUA_TTHREAD vs. LUA_TLIGHTUSERDATA) but not the data.
]

But there are other considerations:

- The question from D. Burgess was (most likely) about a pure Lua approach.

- Every debugger/profiler that is thread-aware needs to implement this
  workaround.

- Every program that wants to account usage of certain functions to a
  thread or to implement thread local storage needs to implement this
  workaround (and requires a C extension).

- Multiple implementations of this workaround are likely to clash.

- It requires cooperation on behalf of the program to be debugged or
  to be profiled. Avoiding having to override coroutine.create was the
  reason Andy Sloane started this topic. :-)

- An extension to the public API is very straightforward and solves that
  issue a lot cleaner with less than 10 lines of code.

Here is the addition to src/lapi.c:

LUA_API void lua_pushthread (lua_State *L, lua_State *L1) { 
  lua_lock(L);
  setthvalue(L, L->top, L1);
  api_incr_top(L);
  lua_unlock(L);
}

And for src/lib/lbaselib.c:

static int luaB_current (lua_State *L) {
  lua_pushthread(L, L);
  return 1;
}
...
  {"current", luaB_current},

> I've never looked to see if threads have separate registries. If they do, 
> you'll need to use lua_xmove() and save the thread to the new registry.

They don't:

lstate.h: #define registry(L)    (&G(L)->_registry)

Having a thread local registry would be interesting for thread local
storage, though. But this is not common enough to warrant an extra table
per thread. A clean solution is to use a global table and index it with
coroutine.current().

Bye,
     Mike