Inform6: Blocking loop

Hello hello!

I’m trying to design a blocking loop that will wait for a file to exist. I’ve tried:

while (FileReady() == false){
    ! Block until data becomes ready
    glk_tick();
}

But it seems to block quixe completely and so the file is never ready as the process to create it never gets to run (supposition).

I also looked at glk_select()/glk_select_poll() on https://www.eblong.com/zarf/glk/Glk-Spec-075.html#event but the available events don’t include external, which is what I would use to communicate.

Could someone tell me what I’ve missed?

It would be better to use a timer to pause and check periodically. That should be more reliable across different interpreters.

Do you mean a timer event and select_poll? If not, can you elaborate?

Yes a timer event and glk_select, not glk_select_poll. If you’re running it in Quixe you need to yield so that other code can run. Browser JS is only single-threaded.

Why not glk_select_poll?

How do you yield in inform? glk_tick()?

Because it’s single threaded no other code will ever get the chance to run.

No, call glk_select, which waits for an event.

I could really be misunderstanding the documentation but I feel like you’ve got them reversed. glk_select() waits and glk_select_poll checks and returns “almost immediately” which would allow my inform code to yield…

I don’t want my inform code to block as I need other code to run.

While the Glk docs say that you should call glk_tick to yield to other processes, in reality in all the Glk implementations I know of it doesn’t, it’s just an empty function. If you actually want to yield you need to call glk_select. It looks like a blocking call, but it will yield appropriately in Quixe and other interpreters.

Conceptually, at least (I’m not sure how it’s implemented), glk_select_poll will return immediately if there is no event pending. Thus, it does not act as a yield at all.

You need to yield back to JS to allow other non-VM code to actually do things (such as generating events!), and glk_select is the way to do that.

If you have other things you want to do while waiting for an event, do it via a timer event.

Based on what the two of you have explained, it seems like I would need to do something like the code below. Could you let me know if I’ve hit the mark?

glk_request_timer_events(500); ! go off around every half second

while (1){
    glk_select(gg_event);

    if (gg_event-->0 == evtype_Timer){
        if (FileReady() == true){
            glk_request_timer_events(0); ! stop timer events

            break;
        }
    }
}

Obviously, this in an infinite loop which is generally bad practice, so if FileReady() never returns true then the loop will never break and the inform code will wait forever, but that’s an issue for the specific implementation. I just want to know if my example is what you two have in mind.

Yep that looks right!

Yes, that should be right.

glk_tick() and glk_select_poll() were both meant for situations that don’t really make sense on modern interpreters. (This was already true in 1997, but I didn’t realize it at the time. If I’d been smarter I would have left them out.)

They both deal with the situation where the game is busy performing some long computation. glk_select_poll() allows the game to check for input during that computation. glk_tick() allows the game to give some time to the operating system – in a cooperative multitasking OS like classic MacOS.

But classic MacOS is a distant memory, and there aren’t many long computations in IF. Counterfeit Monkey has a long startup phase, but that’s still only a few seconds on modern machines. What would you do with user input during startup anyhow? Nothing.

2 Likes