B4J Question Doubt about resumablesub

Status
Not open for further replies.

jroriz

Active Member
Licensed User
Hi.

Let's say I have a sub like this:

B4X:
Sub Process
    Sleep(0)
    ''' long process
End Sub

What's the difference in calling the function like this
Process

or that
Wait For (Process) complete (r As Object)

since the function does not return values.
 

jroriz

Active Member
Licensed User
Ok, I see... But then, if it is in fact equivalent to return, the rest of that sub will not be executed!
And if all you want is for the sub to return, then do just that: Return
See @JordiCP post.
Sleep means return control to the calling sub, and continue executing in background.
The code and log I posted clarify this.
 
Upvote 0

agraham

Expert
Licensed User
It may be helpful to know what is actually happening, it is for me anyway. The code of a Resumable Sub is rewritten by the compiler into a Select statement whose Case sections are blocks of the Sub code so making the Sub a state machine. When a Wait For is encountered the code stores an indication of the next block of code (Case section of the Select statement) to be executed and returns. When the the Wait For ends the Sub is called again from the message loop with a parameter that indicates which Case section of code is to be selected for execution by the Select statement which then executes that section of code.
 
Last edited:
Upvote 0

ThRuST

Well-Known Member
Licensed User
Computer programming is not for everybody anyway, it's for the immortally stubborn lifeforms who hides in caves and never gives up until the sky falls down :)
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
@Erel Please make a new in-deepth tutorial about Resumable subs and the technological processes that it's buildt up of.

I've seen alot of lively discussions about trying to sort this out. I think you're the right man for this job.
 
Upvote 0

ThRuST

Well-Known Member
Licensed User
- I will have to agree to @Daestrum because the Resumable subs is causing so much confusion.

A proper educational tutorial that covers everything in-deepth is what we want.

And when we have covered that, we can have a digital diploma!!!

Please vote for my idea here
 
Upvote 0

jroriz

Active Member
Licensed User
- I will have to agree to @Daestrum because the Resumable subs is causing so much confusion.

A proper educational tutorial that covers everything in-deepth is what we want.

And when we have covered that, we can have a digital diploma!!!

Please vote for my idea here

I think post 17 says more than a thousand words, at least for the purpose for which I opened this thread ...
 
Upvote 0

agraham

Expert
Licensed User
I think that what people here are wanting is an understanding of what is actually happening when a Resumable Sub is used rather than just how to use it. I am not a visual person and do not find it easy to learn from videos and much prefer code samples and written explanations so here is an attempt at a (simplified) written description.

At the heart of the main thread of a B4X application there is a message loop from where all the Subs in the application are called. After a Sub finishes executing it returns to the message loop. The Android OS passes messages to this message loop which in turn calls the appropriate event Sub in the application. While Sub code is running in the application the message loop is stalled and can raise no further events, so a normal Sub cannot wait for an event to happen as the event cannot happen until the message loop is run after the Sub code has returned. Also Android will kill a process that doesn't run its message loop after a few seconds.

So there is a need to conveniently express the sequence, do something, wait for something, then do something. There are several techniques to achieve this, usually all involving a state machine (even if you don't think you are implementing one) that does part of a job, returns to the message loop and then when another event occurs runs more code to finish the job. Typically you might use the value of global variables to decide what needs to be done after the next event and call an appropriate Sub when an event occurs.

The Resumable Sub mechanism allows this "do, wait, then finish" to be conveniently expressed in a single Sub as sections of code separated by WaitFors. It reads as a single Sub but in fact, each section of code runs, returns to the message loop to wait and the Sub is then called again, when the WaitFor expires, to run the appropriate section of code. It is important that local variable values are preserved between invocations of the Sub - in computer science this is called a closure.

You can see the implementation of this in the generated Java code for a Resumable sub. The B4X compiler generates a class for each Resumable Sub. That class has instance fields that carry the local variable values for the Sub, a resume() method that contains the code for the Sub and a state variable that determines which section of the code in the resume() method is executed when resume() is next called. The code in resume() is rewritten by the compiler as a Select statement where the sections of code are placed in different Case statements.

The first call to a Resumable Sub creates the Resumable Sub instance, which sets its internal state to the starting value, and calls its resume() method. When the code execution reaches the Wait For statement it sets the internal state variable to indicate which Case statement to execute on the next call of resume() and calls a B4X internal method that saves a reference to the Resumable Sub class instance, sets up the message loop to call the Sub again when the right event happens and then returns to the Sub which returns to the message loop. The message loop can then carry on doing its job, pumping messages while the Resumable Sub class instance just sits there using no system resources other than a bit of memory.

When the expected event finally occurs code in the message loop calls the resume() method of the saved class instance which then executes the Case statement indicated by its state variable value. If there is another Wait For in the Sub then the same sequence occurs. When a Resumable Sub class instance resume() method finally returns with no further code to run it just returns to the message loop. There are now no saved references to that instance of the Resumable Sub so it is then garbage collected and destroyed.

More than one instance of a Resumable Sub class can be in existence at any one time as a new one is created on every call to a Resumable Sub. These instances are totally separate, have their own state and are independent of each other and live their own life cycles.

I hope this enlightens more than it confuses :)
 
Last edited:
Upvote 0

ByteCounter

Member
Licensed User

Apologies for complaining but IMO some tutorials don't have enough examples of different use cases.
For example on https://www.b4x.com/android/forum/threads/b4x-resumable-subs-sleep-wait-for.78601/#content tutorial only shows waiting for "Complete" event. It doesn't describes use of CallDelayedSub with Wait For to send a "custom" (waited for event) to the internal message queue.

For example, in B4J Main:
B4X:
Sub Process_Globals
 Private tmr1 As Timer
 Private tmr1_count As Int
 Private tmr1_stopcount As Int
End Sub
 
Sub AppStart (Form1 As Form, Args() As String)
  tmr1_stopcount = 4 ' splash screen displayed for 4 seconds
   tmr1.Initialize("Timer1", 1000)
   tmr1.Enabled = True
   Log("Waiting...")
   Wait For background_delay_done
   Log("Code executed past background delay wait for!")
End Sub

Sub Timer1_Tick
   Log("Tick!")
   tmr1_count = tmr1_count + 1
   lblAppTitle.Text = tmr1_count
   If tmr1_count = tmr1_stopcount Then
       Log("Timer disabled")
       tmr1.Enabled = False
       tmr1_count = 0 ' reset for next time
       CallSubDelayed(Me,"background_delay_done")
       ' What CallSubDelayed does here is send "background_delay_done" message to the internal message queue
       ' when the Timer1_Tick sub is finished (CallSubDelayed only runs when the current sub is finished)
       ' This message is caught by Wait For (with same name). In other words you can wait for any specific
       ' event (defined by your string name) and CallSubDelayed is a way to trigger the event.
  
   End If
End Sub

It would be great if tutorials were periodically updated based on forum questions, so the tutorials are "living" and added to over time.
I feel this would significantly reduce confusion.
 
Upvote 0

Erel

Administrator
Staff member
Licensed User
Your post is not really related to this thread.

The code is very complicated for no good reason.
You can replace the complete code with:
B4X:
Sub AppStart (Form1 As Form, Args() As String)
   Log("Waiting...")
   Sleep(4000)
   Log("Code executed past background delay wait for!")
End Sub
tutorial only shows waiting for "Complete" event
It shows how to wait for all kinds of events.
It would be great if tutorials were periodically updated based on forum questions
When the tutorial was first written it did show how to use CallSubDelayed as a solution for waiting for a resumable sub to complete. A few versions later a more powerful and simpler method was added with the ResumableSub object (https://www.b4x.com/android/forum/threads/b4x-resumable-subs-that-return-values-resumablesub.82670/). So the tutorial was updated.
In most cases, as in the case you posted, the usage of CallSubDelayed is not required and is actually a bad practice.

For further discussion please start a new thread.
 
Upvote 0
Status
Not open for further replies.
Top