Is there a way to pause lua_pcall() and resume later?

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Is there a way to pause lua_pcall() and resume later?

Andreas Falkenhahn-2
Hi,

I'm wondering if there is a way to pause script execution during lua_pcall() and resume it later at the paused position?

Here's the background of my problem: I have created a wrapper for some Android UI functions so that they can be called from a Lua script, e.g.

    bt:setLabel("Tap me")

Now when the user taps the button, the Java code makes a JNI call to C code which then calls lua_pcall() to run a Lua function handling the respective event. This all works fine so far except when it comes to functions that use a modal loop to block until the user has responded, e.g.

    showMessageBox("Important message for you, please acknowledge before we go on")

Since Android doesn't have the concept of modal loops, lua_pcall() needs to return control to the UI thread immediately even though the user hasn't closed the message box created by showMessageBox() yet. So when entering my showMessageBox() implementation I'd somehow need to tell lua_pcall() to pause its execution and resume it later when the user has closed the message box. Is that possible somehow?

I have also thought about circumventing the problem by having Lua run on its own thread but that won't work because it will call into functions which need to be run on the UI thread and delegating them to the UI thread isn't an option because that will lead to a deadlock in the following situation:

- UI thread receives a "button clicked" event and tells the Lua thread to run lua_pcall()

- the code that is run by lua_pcall() on the Lua thread now could then run functions like setLabel() to change the label of a button widget but this will deadlock now because setLabel() can only be called on the UI thread so the Lua thread will be waiting for the UI thread while the UI thread will be waiting for the Lua thread... deadlock!

So the only option I see here is to find a way to pause lua_pcall() and resume it later to solve the modal loop problem. That feels like a somewhat ugly solution but I don't see any other way. So is that possible somehow or would it have to be hacked into the VM?

Thanks for ideas!

--
Best regards,
 Andreas Falkenhahn                          mailto:[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Is there a way to pause lua_pcall() and resume later?

Viacheslav Usov
On Mon, Aug 12, 2019 at 3:17 PM Andreas Falkenhahn <[hidden email]> wrote:

> Since Android doesn't have the concept of modal loops, lua_pcall() needs to return control to the UI thread immediately even though the user hasn't closed the message box created by showMessageBox() yet. So when entering my showMessageBox() implementation I'd somehow need to tell lua_pcall() to pause its execution and resume it later when the user has closed the message box. Is that possible somehow?

I doubt this problem is really about Lua. You real issue is that whatever you do on the UI thread should not block it. If you "pause" it, that will still block it. So whatever you call on the UI thread should readily return - it cannot enter showMessageBox() and just stay there.

If I knew more about Android, I'd say you might also consider running the message/event loop within your implementation, thus alleviating the need to return from it, but, again, I am really just groping in the dark here.

Cheers,
V.
Reply | Threaded
Open this post in threaded view
|

Re: Is there a way to pause lua_pcall() and resume later?

Andreas Falkenhahn-2
On 12.08.2019 at 15:39 Viacheslav Usov wrote:

> I doubt this problem is really about Lua. You real issue is that whatever you do on the UI thread should not block it. If you "pause" it, that will still block it.

To clarify, what I mean by "pause" is that lua_pcall() must return so that control is back on the UI thread. Later, once I have received the event that the message box has been closed, I want to "resume" the previous call to lua_pcall().

> If I knew more about Android, I'd say you might also consider running the message/event loop within your implementation

AFAIU this is not possible because Android doesn't support modal loops at all.

--
Best regards,
 Andreas Falkenhahn                            mailto:[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Is there a way to pause lua_pcall() and resume later?

Viacheslav Usov
On Mon, Aug 12, 2019 at 3:45 PM Andreas Falkenhahn <[hidden email]> wrote:

> To clarify, what I mean by "pause" is that lua_pcall() must return so that control is back on the UI thread. Later, once I have received the event that the message box has been closed, I want to "resume" the previous call to lua_pcall().

Then just make it return. And then call it again. Do not block while in the call.

As I said, the issue is not in Lua, it is in the way you do things. Imagine there is no Lua at all and you just do the whole thing in C - how would you do it?

You probably could make the whole thing fancier in Lua by using co-routines, but, ultimately, the code running in the UI thread - that is to say, the code handling a UI event - must return - or yield - as soon as possible to avoid blocking the UI.

If you need blocking calls, use non-UI threads for them.

All of the above assumes Android cannot have multiple UI threads within one application.

Cheers,
V.
v
Reply | Threaded
Open this post in threaded view
|

Re: Is there a way to pause lua_pcall() and resume later?

v
On Mon, 2019-08-12 at 16:18 +0200, Viacheslav Usov wrote:

> On Mon, Aug 12, 2019 at 3:45 PM Andreas Falkenhahn <
> [hidden email]> wrote:
>
> > To clarify, what I mean by "pause" is that lua_pcall() must return
> so that control is back on the UI thread. Later, once I have received
> the event that the message box has been closed, I want to "resume"
> the previous call to lua_pcall().
>
> Then just make it return. And then call it again. Do not block while
> in the call.

Or use Lua coroutines to make code easier to read. They really can save
the day when it comes to asynchronous code.

Together with `coroutine.wrap` it will require little to no effort on C
side.

--
v <[hidden email]>


Reply | Threaded
Open this post in threaded view
|

Re: Is there a way to pause lua_pcall() and resume later?

Philippe Verdy
I wqould say that if your application requires a blocking pcall, that application MUST NOT run in the main UI thread but must run in another thread that you can suspend by yielding back to the UI thread, where your Lua wrapper will just be a "very light" event dispatcher  (that will resume the application's thread when needed according to some "wait" condition)

It's perfectly possible to write a blocking behavior outside the main UI thread. 

The dispatcher will resume the application by giving it the event, the application will determine if that event is sufficient to exit its blocking event loop and return from its local "pcall"; if that event does not wualify, the application will yield back to the main thread of the dispatcher or to other competing threads, discarding that event).

For all this, you just need to use coroutines: your blocking application will be running in a separate coroutine that can be suspended and resumed at any time and your application is free to yield() at any time, even in non-blocking situations (and here also the light dispatcher in the main thread can handle that situation).