[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Lua 5.1 upvalues
- From: "Robert G. Jakabosky" <bobby@...>
- Date: Sat, 9 Apr 2011 01:37:07 -0700
On Saturday 09, Anthony Howe wrote:
> On 09/04/2011 00:59, Robert G. Jakabosky whispered from the shadows...:
> > That code should be:
> >
> > lua_newtable(L);
> > lua_pushvalue(L, -1);
> > lua_pushcclosure(L, &foobar, 1);
> > lua_pushvalue(L, -2);
> > lua_pushcclosure(L, &barblat, 1);
> > lua_remove(L, -3);
>
> Ok. Thanks.
>
> > Like others have said they can shared the same value, but not the same
> > 'local' storage of that value. As long as you don't try to store a new
> > value in the upvalue of one C closure and expect the other C closure to
> > see the new value.
>
> I was thinking along those lines, but the above example works too.
>
> The upvalue solution should work for C functions called by Lua that need
> a context. I presume that upvalues/C closures are tied the Lua thread
> state?
The upvalues are tied to the closure (i.e. the instance of the function) not
to the Lua thread. Upvalues are not unique to a Lua thread. Two threads
calling the same closure instance will use the same 'local' variable storage.
> > Lua closures can share the same 'local' storage for an upvalue:
> > local shared_storage = 123
>
> Q: When loading a Lua script into a master state, do Lua threads a) get
> a copy of local variables, b) get their own version of those local
> variables (copy by value, not by reference) such that two threads can
> have a variable by the same name, but assign different values?
Again local variables are tied to the closure not the thread. Just to be
clean by Lua threads I mean Lua coroutines (even the lua_newthread() C
function creates a coroutine not a OS thread).
Example:
local foo=1
function thread_func()
repeat
print(foo)
foo = foo + 1
coroutine.yield()
until false
end
local co = coroutine.create(thread_func)
coroutine.resume(co) -- thread 1 output: 1
print(foo) -- main thread output: 2
coroutine.resume(co) -- thread 1 output: 2
print(foo) -- main thread output: 3
local co2 = coroutine.create(thread_func)
coroutine.resume(co2) -- thread 2 output: 3
coroutine.resume(co) -- thread 1 output: 4
coroutine.resume(co2) -- thread 2 output: 5
print(foo) -- main thread output: 6
All of that code is part of the main Lua function which is executed by the
main Lua thread. That main function has a local variable 'foo' that it shares
with the Lua closure 'thread_func'. The two threads are created with the same
closure which has a reference to the 'foo' local variable.
You could create different Lua closures for each thread:
function create_counter()
local counter = 1
-- create a new Lua closure
-- each closure gets it's own 'counter' variable as an upvalue.
return function ()
repeat
print(counter)
counter = counter + 1
coroutine.yield()
until false
end
end
local co = coroutine.create(create_counter())
local co2 = coroutine.create(create_counter())
coroutine.resume(co) -- thread 1 output: 1
coroutine.resume(co) -- thread 1 output: 2
coroutine.resume(co2) -- thread 2 output: 1
coroutine.resume(co) -- thread 1 output: 3
coroutine.resume(co) -- thread 1 output: 4
coroutine.resume(co2) -- thread 2 output: 2
--
Robert G. Jakabosky