lua-users home
lua-l archive

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


On Sat, Jun 6, 2015 at 4:50 PM, Laurent FAILLIE <l_faillie@yahoo.com> wrote:
> Hello,
>
> I have another question related to Lua's stat which is expected to be passed
> as 1st arg for Lua's function : is it thread safe ?

No.

I use definitions of thread-safety and reentrancy from Qt documentation.

By default [*], Lua functions are reentrant (i.e., C functions could
be called safely with different Lua states by multiple threads at the
same moment), but not thread-safe (i.e., a Lua state must not be used
by two threads at the same moment).

You can use N Lua states in N threads (1 thread = 1 Lua state), but
you could not use 1 Lua state in N threads.

One Lua state can be used by multiple threads, but not at the same
moment. In this case a Lua state is "passed" from thread to thread.
Some applications use multiple OS threads, multiple Lua states, each
with multiple Lua threads. For example, nginx does so. It can spawn
multiple workers (= OS threads). Each worker starts a Lua state. Lua
states are shared by OS threads, but no Lua state is operated by two
OS threads at the same moment. When HTTP request is accepted, it is
passed to one of workers, starting a Lua thread. If then request
handler makes something asynchronous (i.e., database query), this Lua
thread is yield'ed. When that asynchronous task is finished, then the
Lua thread resumes the request handler. It can happen in any worker
though (but in same Lua state, of course). Selection of a worker
depends on availability of workers and on configuration. For instance,
it makes sense to wait for the worker which worked with this Lua
thread before to reuse processor cache.

Thus it is thread-safe to reuse Lua state (e.g., resume Lua thread) in
other OS thread.


> My application handles MQTT messages in asynchronous mode meaning messages
> handling (and consequently the Lua callbacks I want to call for every
> arriving messages) is running in a separate thread ... but it is safe to use
> the same lua_stat ? what will happen if a message arrive whereas the main
> thread is already running a Lua function ?

I hope I answered this part of your question as well.

By the way, consider using Lua threads instead of callbacks, as nginx
does. Lua code using nginx functions looks like synchronous code.

Compare:

  users = database.query "select * from users;"

with

  database.query("select * from users;", function(users)
    -- do smth with users
  end)

[*] You can achieve thread-safety by defining functions lua_lock and
lua_unlock, which are called by all Lua API functions.

>
> Thanks
>
> Laurent
>
> The misspelling master is on the Web.
>   _________ 100 % Dictionnary Free !
> /               /(
> / Dico       / / Pleins d'autres fautes sur
> /________/ /
> (#######( / http://destroyedlolo.info
> Quoi, des fautes d'orthographe! Pas possible ;-D.
>
>
>
> Le Mercredi 3 juin 2015 15h03, Laurent FAILLIE <l_faillie@yahoo.com> a écrit
> :
>
>
> Ok, thanks to all for your replies.
>
> I'll make some tests with the provided information and will post the result
> (if it can help someone else).
>
> Thanks
>
> Laurent----
> The misspelling master is on the Web.
>   _________ 100 % Dictionnary Free !
> /               /(
> / Dico       / / Pleins d'autres fautes sur
> /________/ /
> (#######( / http://destroyedlolo.info
> Quoi, des fautes d'orthographe! Pas possible ;-D.
>
>
>
> Le Mercredi 3 juin 2015 14h19, Roberto Ierusalimschy
> <roberto@inf.puc-rio.br> a écrit :
>
>
>>  Another way is to store a reference in the Lua Registry:
>>
>>      int myfuncref;
>>
>>      static int foo(lua_State *L)
>>      {
>>
>>        luaL_checktype(L,1,LUA_TFUNCTION);
>>        myfuncref = luaL_ref(L,LUA_REGISTRYINDEX);
>>        lua_pushinteger(L,myfuncref);
>>        lua_pushvalue(L,1);
>>        lua_settable(L,LUA_REGISTRYINDEX);
>>        return 0;
>>      }
>
> luaL_ref does all the work (see the manual). This function should be
> like this:
>
>       static int foo(lua_State *L) {
>           luaL_checktype(L,1,LUA_TFUNCTION);
>           myfuncref = luaL_ref(L,LUA_REGISTRYINDEX);
>           return 0;
>         }
>
>
>>  And to call that:
>>
>>      static int bar(lua_State *L)
>>      {
>>        lua_pushinteger(L,myfuncref);
>>        lua_gettable(L,LUA_REGISTRYINDEX);
>>        lua_call(L,0,0);
>>        return 0;
>>      }
>
> (It is simpler to use 'lua_rawgeti'...)
>
> -- Roberto
>
>
>
>
>



-- 


Best regards,
Boris Nagaev