lua-users home
lua-l archive

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


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