lua-users home
lua-l archive

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


Viacheslav:

On Tue, May 21, 2019 at 1:32 PM Viacheslav Usov <via.usov@gmail.com> wrote:
> On Tue, May 21, 2019 at 11:47 AM Francisco Olarte <folarte@peoplecall.com> wrote:
> > For a program I'm doing I need to use a single interpreter from multiple threads. I do not have problems in the normal case, just lock/unlock around usage, but some times I need to "reenter".
> I would stay away from that.

I really tried.

> If you can ensure that ostA, while waiting for a message, is not using Lua (except holding some memory for its Lua API stack)

Waiting for the reply to message is synchronous. ostA, after
unlocking, calls a C function, and relocks at return.

> and ostB is not using Lua _in_any_way_ when and after it sends a message to ostA,

ostB is, in this case, invoked by the function called by A sending a
message to it's queue. Sending blocks A until B replies, it's a
syncronous send.

> then you have already achieved a fully synchronised execution of those threads with respect to Lua and no further locks can make it any safer. Those locks will probably only give you an inflated sense of security.

I need a lock in the interpreter because I have more than one thread
wanting to use it, let's say A1, A2, I do not want A2 entering while
A1 is in, I do not mind it entering/exiting while A1 is waiting for B.

> The emphasis on "in any way" is supposed to mean that all of the calls into Lua have returned in this thread and none will be made (till another cycle begins).

If ostA calls into ostB indirectly, it is blocked waiting for a
response. It has called a synchronous sendmessage, will not do nothing
until B is out of the interpreter and replies.

> Your approach a/b, at first glance, looks like it might work and it is indeed similar to the paradigm used by Lua itself. The question is how generally robust that paradigm is. Imagine thread A does this:
> lock(); push_value(); unlock(); do_something_not_touching_Lua(); lock(); pop_value(); unlock();
> (where values are pushed and popped on the Lua API stack)
> And thread B does this:
> lock(); push_another_value(); unlock(); do_something_not_touching_Lua_2(); lock(); pop_value(); unlock();

1st, the "do something not touching lua" is always "wait", the thread
is not doing nothing fancy.

When ostA decides it wants something done in lua it locks the state,
pushes args, calls a function, pops return value, unlocks.

Whenever it needs to call the core I unlock/lock I leave the state
"clean", I mean, empty stack. ostA,  inside Lua has called the a C
function. The C function then get args from the state, and, if it
needs to call some core function which may reenter, clears the stack,
unlocks, calls core function, relocks, pushed return values, returns
into lua. Everytime the state is unlocked, the stack is empty. If I
need to do a sequence of opertations manipulating the stack ALL is
done locked.

> What value each thread is going to pop? Do you even want to have to answer such questions?

No, that's why I clear the stack before unlocking. Same as I assure my
global state objects are in a consistent quiescent state when I do
similar things in C++. I'm not going to be doing this a lot, and I've
designed the system in a way in which the normal sending of messages
does not involve syncing ( I yield a message as a table from lua, and
resume with the reply when needed ), but sometimes a C function in the
core MAY send me a message from another thread from deep inside.

Francisco Olarte.