B4J Question ResumableSub and ConnectionPool

Enrique Gonzalez R

Well-Known Member
Licensed User
Hi!

i have the following sub

B4X:
Public Sub getCon As ResumableSub
   pool.GetConnectionAsync("con")   
   wait for con_ConnectionReady (Success As Boolean, sql As SQL)
   
   If Success Then
       Return sql
   Else
       Return Null
   End If
End Sub
the problem with it is that if 2 or 3 subs call the same sub, it will not run the formers because of how ResumableSub works

is it posible that GetConnectionAsync return an object to be used as a filter?

thank you!
 

OliverA

Expert
Licensed User

Enrique Gonzalez R

Well-Known Member
Licensed User

OliverA

Expert
Licensed User
Thanks @Enrique Gonzalez R for clarifying that.
@XbNnX_507, @Enrique Gonzalez R is correct. See code at end (it's a tad long, so I'm posting it at the end. It's B4J, Non-UI). The results are
Starting sequence # 1
Starting PauseALittle #1 for 2 seconds
Starting sequence2 # 1
Starting PauseALittle2 #1 for 2 seconds
Starting PreSequenceTest3 # 1
Starting sequence3 # 1
Starting PauseALittle3 #1 for 2 seconds
Starting sequence # 2
Starting PauseALittle #2 for 3 seconds
Starting sequence2 # 2
Starting PauseALittle2 #2 for 3 seconds
Starting PreSequenceTest3 # 2
Starting sequence3 # 2
Starting PauseALittle3 #2 for 3 seconds
Starting sequence # 3
Starting PauseALittle #3 for 4 seconds
Starting sequence2 # 3
Starting PauseALittle2 #3 for 4 seconds
Starting PreSequenceTest3 # 3
Starting sequence3 # 3
Starting PauseALittle3 #3 for 4 seconds
Starting sequence # 4
Starting PauseALittle #4 for 5 seconds
Starting sequence2 # 4
Starting PauseALittle2 #4 for 5 seconds
Starting PreSequenceTest3 # 4
Starting sequence3 # 4
Starting PauseALittle3 #4 for 5 seconds
Starting sequence # 5
Starting PauseALittle #5 for 1 seconds
Starting sequence2 # 5
Starting PauseALittle2 #5 for 1 seconds
Starting PreSequenceTest3 # 5
Starting sequence3 # 5
Starting PauseALittle3 #5 for 1 seconds
Starting sequence # 6
Starting PauseALittle #6 for 2 seconds
Starting sequence2 # 6
Starting PauseALittle2 #6 for 2 seconds
Starting PreSequenceTest3 # 6
Starting sequence3 # 6
Starting PauseALittle3 #6 for 2 seconds
Starting sequence # 7
Starting PauseALittle #7 for 3 seconds
Starting sequence2 # 7
Starting PauseALittle2 #7 for 3 seconds
Starting PreSequenceTest3 # 7
Starting sequence3 # 7
Starting PauseALittle3 #7 for 3 seconds
Starting sequence # 8
Starting PauseALittle #8 for 4 seconds
Starting sequence2 # 8
Starting PauseALittle2 #8 for 4 seconds
Starting PreSequenceTest3 # 8
Starting sequence3 # 8
Starting PauseALittle3 #8 for 4 seconds
Starting sequence # 9
Starting PauseALittle #9 for 5 seconds
Starting sequence2 # 9
Starting PauseALittle2 #9 for 5 seconds
Starting PreSequenceTest3 # 9
Starting sequence3 # 9
Starting PauseALittle3 #9 for 5 seconds
Starting sequence # 10
Starting PauseALittle #10 for 1 seconds
Starting sequence2 # 10
Starting PauseALittle2 #10 for 1 seconds
Starting PreSequenceTest3 # 10
Starting sequence3 # 10
Starting PauseALittle3 #10 for 1 seconds
Finished PauseALittle #5
Finished PauseALittle2 #5
Stopping sequence #5, after waiting for PauseALittle #5
Finished PauseALittle3 #5
Stopping sequence2 #10, after waiting for PauseALitte2 #5
Stopping sequence3 #10, after waiting for PauseALittle3 #5
Finished PauseALittle #10
Finished PauseALittle2 #10
Finished PauseALittle3 #10
Stopping PreSequenceTest3 #10, after waiting for SequenceTest3 #5
Stopping sequence #10, after waiting for PauseALittle #10
Finished PauseALittle #1
Stopping sequence #1, after waiting for PauseALittle #1
Finished PauseALittle2 #1
Finished PauseALittle3 #1
Finished PauseALittle #6
Finished PauseALittle2 #6
Finished PauseALittle3 #6
Stopping sequence #6, after waiting for PauseALittle #6
Finished PauseALittle #2
Finished PauseALittle2 #2
Finished PauseALittle3 #2
Stopping sequence #2, after waiting for PauseALittle #2
Finished PauseALittle #7
Finished PauseALittle2 #7
Finished PauseALittle3 #7
Stopping sequence #7, after waiting for PauseALittle #7
Finished PauseALittle #3
Finished PauseALittle2 #3
Finished PauseALittle3 #3
Stopping sequence #3, after waiting for PauseALittle #3
Finished PauseALittle #8
Finished PauseALittle2 #8
Finished PauseALittle3 #8
Stopping sequence #8, after waiting for PauseALittle #8
Finished PauseALittle #4
Finished PauseALittle2 #4
Finished PauseALittle3 #4
Stopping sequence #4, after waiting for PauseALittle #4
Finished PauseALittle #9
Finished PauseALittle2 #9
Finished PauseALittle3 #9
Stopping sequence #9, after waiting for PauseALittle #9
Notice that for every "sequence" that is started, there is a corresponding "stopping sequence" log entry. But for "PreSequenceTest3", "sequence2" and "sequence3", there is only one stopping message:
Stopping sequence2 #10, after waiting for PauseALitte2 #5
Stopping sequence3 #10, after waiting for PauseALittle3 #5
Stopping PreSequenceTest3 #10, after waiting for SequenceTest3 #5
Each logs the last call of each function (#10), put posts the first wait for that was completed (#5). BTW, why did I make the test this long? At first I thought that @Enrique Gonzalez R meant that Resumable subs have to finish in order called or return results in order called instead of order completed.
B4X:
Sub AppStart (Args() As String)
    SequenceTest(1)
    SequenceTest2(1)
    PreSequenceTest3(1)
    SequenceTest(2)
    SequenceTest2(2)
    PreSequenceTest3(2)
    SequenceTest(3)
    SequenceTest2(3)
    PreSequenceTest3(3)
    SequenceTest(4)
    SequenceTest2(4)
    PreSequenceTest3(4)
    SequenceTest(5)
    SequenceTest2(5)
    PreSequenceTest3(5)
    SequenceTest(6)
    SequenceTest2(6)
    PreSequenceTest3(6)
    SequenceTest(7)
    SequenceTest2(7)
    PreSequenceTest3(7)
    SequenceTest(8)
    SequenceTest2(8)
    PreSequenceTest3(8)
    SequenceTest(9)
    SequenceTest2(9)
    PreSequenceTest3(9)
    SequenceTest(10)
    SequenceTest2(10)
    PreSequenceTest3(10)
    StartMessageLoop
End Sub

Sub SequenceTest(id As Int)
    Log($"Starting sequence # ${id}"$)
    wait for (PauseALittle(id)) complete (myId As Int)
    Log($"Stopping sequence #${id}, after waiting for PauseALittle #${myId}"$)
End Sub

Sub PreSequenceTest3(id As Int)
    Log($"Starting PreSequenceTest3 # ${id}"$)
    Wait for (SequenceTest3(id)) Complete (myId As Int)
    Log($"Stopping PreSequenceTest3 #${id}, after waiting for SequenceTest3 #${myId}"$)
End Sub

Sub SequenceTest3(id As Int) As ResumableSub
    Log($"Starting sequence3 # ${id}"$)
    PauseALittle3("con3", id)
    Wait for con3_doneit (myId As Int)
    Log($"Stopping sequence3 #${id}, after waiting for PauseALittle3 #${myId}"$)
    Return myId   
End Sub

Sub SequenceTest2(id As Int)
    Log($"Starting sequence2 # ${id}"$)
    PauseALittle2("con2", id)
    Wait for con2_doneit (myId As Int)
    Log($"Stopping sequence2 #${id}, after waiting for PauseALitte2 #${myId}"$)
End Sub

Sub PauseALittle(id As Int) As ResumableSub
    Dim pauseTime As Int = (id Mod 5) + 1
    Log($"Starting PauseALittle #${id} for ${pauseTime} seconds"$)
    Sleep(pauseTime * 1000)
    Log($"Finished PauseALittle #${id}"$)
    Return id
End Sub

Sub PauseALittle2(callback As String, id As Int)
    Dim pauseTime As Int = (id Mod 5) + 1
    Log($"Starting PauseALittle2 #${id} for ${pauseTime} seconds"$)
    Sleep(pauseTime * 1000)
    Log($"Finished PauseALittle2 #${id}"$)
    CallSubDelayed2(Me, callback & "_doneit", id)
End Sub

Sub PauseALittle3(callback As String, id As Int)
    Dim pauseTime As Int = (id Mod 5) + 1
    Log($"Starting PauseALittle3 #${id} for ${pauseTime} seconds"$)
    Sleep(pauseTime * 1000)
    Log($"Finished PauseALittle3 #${id}"$)
    CallSubDelayed2(Me, callback & "_doneit", id)
End Sub
 

Enrique Gonzalez R

Well-Known Member
Licensed User
Lol. That's the same what i said.:D


Hola Enrique, How are you calling the sub getCon ?


I think the correct way to call it is with this sub, correct me if i'm wrong.
B4X:
Sub CallGetCon
       dim filter as resumablesub = getCon
       wait for ( filter) Complete ( con as sql )
End Sub
Yes! that is the way i called it, actually i designed that Sub to be called like that.

Thanks @Enrique Gonzalez R for clarifying that.
Yes @OliverA ! my english has worsen since i no longer exercise my skill. long ago, i used to speak, write and hear on a daily basis english, but no longer.

BTW, why did I make the test this long?
No idea...

@XbNnX_507, @Enrique Gonzalez R is correct. See code at end
yep, Erel has implemented a senderfilter on other official libraries but there are too many, i hope he updates this one.
 

Erel

Administrator
Staff member
Licensed User
There is a problem with implementing your request. It means that the "sender" object will be changed to something else instead of the pool itself (it is partially related to the object being a wrapper object).
This will make the Sender keyword non-useful with this object and will break existing code that relies on it to return the pool.

I also don't think that your sub is needed. You will need to call this sub with Wait For anyway. It will not make the code simpler than getting the connection directly:
B4X:
 pool.GetConnectionAsync("MyCon")  
 wait for MyCon_ConnectionReady (Success As Boolean, sql As SQL)
'work with sql
 sql.Close
 
Top