[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Multiple functions: was the gc
- From: Andrew Teirney <andrew@...>
- Date: Thu, 24 Aug 2006 20:42:12 +1200
D Burgess wrote:
... functions to instantiate "environment-less"
functions which bind dynamically when called.
This would do the trick for me.
I thought i might as well post this message to the lua mailing list,
previously i personally emailed this to Mr Burgess to get his feedback,
it seems as though it does what he is after. I now unleash this to
public forum for comments.
...
I was following the thread on the lua list as the ability for a function
to use the threads global environment rather than the environment
inherited during the closure creation has great appeal to me. I myself
wanted to be able to alter functions to use the globals of the thread in
which they are invoked as opposed to having the hassles of managing
multiple closures for multiple lua threads.
I have attached a patch which i think does what you want, it certain
does what i want to do.
This is the code that i used to do my testing, at present the only
function that will take dynamically binded global values from the
thread is the "count" function. To the clearing of the closure
environment i added a clearenv function and put the necessary support
into the lua core.
Andrew
*testing.lua*
count = function(start, name)
j = start
for i = 1, 4 do
print("in thread " .. name .. ", j = " .. j)
j = j + 1
coroutine.yield()
end
print("thread " .. name .. " is done!")
end
newthread = function(start, name)
local th = coroutine.create(function()
-- replace the threads environment with a simple environment
local t = { print = print, tostring = tostring, coroutine = coroutine }
setfenv(0, t)
-- the the actual thread operation
print("thread " .. name .. " starting...");
count(start, name)
print("thread " .. name .. " is finished!");
end);
return th
end
-- clear count environment, we want it to use the threads global env
clearfenv(count)
-- prepare two threads to run function count.
t1 = newthread(1, "t1")
t2 = newthread(10, "t2")
-- set the master global value to something that we can check to make
sure it doesn't change
j = 123
-- execute the coroutines
coroutine.resume(t1)
coroutine.resume(t1)
coroutine.resume(t1)
coroutine.resume(t2)
coroutine.resume(t1)
coroutine.resume(t2)
coroutine.resume(t1)
coroutine.resume(t2)
coroutine.resume(t2)
coroutine.resume(t2)
-- ensure the master j value has not changed
print("j = " .. j);
*output.txt*
thread t1 starting...
in thread t1, j = 1
in thread t1, j = 2
in thread t1, j = 3
thread t2 starting...
in thread t2, j = 10
in thread t1, j = 4
in thread t2, j = 11
thread t1 is done!
thread t1 is finished!
in thread t2, j = 12
in thread t2, j = 13
thread t2 is done!
thread t2 is finished!
j = 123
diff -r lua-5.1.1/src/lapi.c lua-5.1.1.patched/src/lapi.c
758a759,778
> LUA_API int lua_clearfenv (lua_State *L, int idx) {
> StkId o;
> int res = 1;
> lua_lock(L);
> api_checknelems(L, 1);
> o = index2adr(L, idx);
> api_checkvalidindex(L, o);
> switch (ttype(o)) {
> case LUA_TFUNCTION:
> clvalue(o)->c.env = NULL;
> break;
> default:
> res = 0;
> break;
> }
> lua_unlock(L);
> return res;
> }
>
>
diff -r lua-5.1.1/src/lbaselib.c lua-5.1.1.patched/src/lbaselib.c
160a161,169
> static int luaB_clearfenv (lua_State *L) {
> getfunc(L);
> if (lua_iscfunction(L, -1) || lua_clearfenv(L, -1) == 0)
> luaL_error(L,
> LUA_QL("clearfenv") " cannot change environment of given object");
> return 1;
> }
>
>
446a456
> {"clearfenv", luaB_clearfenv},
diff -r lua-5.1.1/src/lgc.c lua-5.1.1.patched/src/lgc.c
225c225,226
< markobject(g, cl->c.env);
---
> if (cl->c.env)
> markobject(g, cl->c.env);
diff -r lua-5.1.1/src/lua.h lua-5.1.1.patched/src/lua.h
195a196
> LUA_API int (lua_clearfenv) (lua_State *L, int idx);
diff -r lua-5.1.1/src/lvm.c lua-5.1.1.patched/src/lvm.c
433c433
< Protect(luaV_gettable(L, &g, rb, ra));
---
> Protect(luaV_gettable(L, cl->env ? &g : gt(L), rb, ra));
444c444
< Protect(luaV_settable(L, &g, KBx(i), ra));
---
> Protect(luaV_settable(L, cl->env ? &g : gt(L), KBx(i), ra));