QB64 Phoenix Edition
Through traffic or no? - Printable Version

+- QB64 Phoenix Edition (https://qb64phoenix.com/forum)
+-- Forum: Chatting and Socializing (https://qb64phoenix.com/forum/forumdisplay.php?fid=11)
+--- Forum: General Discussion (https://qb64phoenix.com/forum/forumdisplay.php?fid=2)
+--- Thread: Through traffic or no? (/showthread.php?tid=3243)



Through traffic or no? - Pete - 12-02-2024

Back in the Stone Age, when computers did not have clocks in the taskbar, I made my own clock routine to display the time. The problem was it needed to be constantly looped to keep the time displayed accurately. To accomplish this, I made all my sub-routines flow-through routines. No matter how nested the routines became, the program always flowed back to and cycled through the main. Now that was a PITA when it came to variable management, but at least I didn't have to place a clock call in every sub-routine that had loop routines. 

How about the rest of you folks; what method do you prefer to use for large projects when it comes to keeping the flow in each routine or always passing control back through the main? Currently I favor avoiding flow-through routines.

Pete


RE: Through traffic or no? - Petr - 12-02-2024

Hi. I'll just put it in the same subroutine that draws the output graphic fields. And depending on whether it should be on top or below something, the order of drawing is just set.

Continuous subroutines are sometimes needed, for example for the mouse, for the keyboard and so on.


RE: Through traffic or no? - Pete - 12-02-2024

I always combine my keyboard input and mouse routines in a single sub. If I knew back then what I know now, I would have combined the clock routine in that sub-routine, too. Then just call the keyboard/mouse/clock in every program closed loop. It was a bit harder back then, with multi-modular programming, but still doable. By using TYPE variables, there is a lot less to code to pass variables so that is helpful, but I wish we could type arrays. Back then to save on memory, I used almost all global variables no longer than 2 characters. Lucky for you guys I was a chiropractor, because if not, the cost of your aspirin would have been double back then, due to supply shortages!

Pete

- Pete is tremendous but Steve's just amazing!


RE: Through traffic or no? - SMcNeill - 12-02-2024

Usually when I need to do what Pete is suggesting, I create a self-monitoring routine and only have it report an a solution once it's finished.

Let's say I have an interactive game where you're in a spaceship flying around with other players all connected via TCP/IP.  You can use the mouse to move and interact with the spaceship.  You want to type a message to others.

Now, at this point, you DON'T want the game to freeze up, so I'd set a few flags.

IF ALT + M THEN 'the player hit the alt-m buttons to flag they were sending a message
    PlayerMessage = True  'set a flag so we now check for what they're typing
END IF

Below all these flag setters, I'd have some code to call my routines:
IF PlayerMessage Then 
    Msg2Send$ = GetInputForMessage
    IF Msg2Send$ <> "" THEN PlayerMessage = 0 'we got a message.  we don't need to look for anymore
END IF

And outside my main loop would be something like:

FUNCTION GetInputForMessage$ (k as Long) 'key is my key stroke as read in the main loop and passed along faithfully
    STATIC partMsg$
    IF k <> CHR$(13) THEN
      partMsg$ = partMsg$ + chr$(k)
    ELSE
       GetInputForMessage = partMsg$ 'the player hit ENTER, finishing what he was trying to type in
       partMsg$ = ""
     END IF
END FUNCTION



The idea here is that main loop keeps looping.  The subroutines ONLY get called when necessary to reduce strain and resource usage in the main loop.  Those subroutines ONLY return a value once they're finished do whatever they do, otherwise, they just return blank.  

If it's a routine that returns a number, I'll choose some fanciful non-existent type number for them, or else I'll pass a FINISHED flag with them if I can't pass an invalid solution.  For example, think of a routine that asks for someone to enter a number from 0 to 9.  IF they haven't hit 0 to 9 yet, I'd simply return a value of 123 as a "nope!  no valid info here yet.  We're still counting fingers and toes waiting on it..."

So a lot of my longer junk that I code relies on this style coding.  Set a flag, only check the routine when that flag is set, keep checking it until that flag is cleared or the process is complete, use the completed result and reset that flag so we don't check that routine anymore and free up processing cycles.


RE: Through traffic or no? - Pete - 12-02-2024

Similar to just setting a flag but doing so with an event...

Code: (Select All)
' Main
Cls
Locate 10, 2: Print "Message";: Color 7 + 16: Print ":";: Color 7, 0
Do

    keyboard key$

    If Len(key$) Then
        If LCase$(key$) >= "a" And LCase$(key$) <= "z" Or key$ = " " Then

            message key$

            If key$ = Chr$(13) Then
                Locate 10, 11: Print Space$(_Width - Pos(0)); ' Message sent.
                Locate 10, 2: Print "Message";: Color 7 + 16: Print ":";: Color 7, 0 ' Ready for next message.
            End If
            If key$ = Chr$(27) Then Exit Do
        End If
    End If

    animate

Loop
End

Sub keyboard (key$) ' Flow-through sub-routine.
    _Limit 30
    key$ = InKey$
End Sub

Sub message (key$) ' Non-flow-through sub-routine.
    y = 10: x = 10
    Locate 10, 2: Print "Message:"; ' Stops colon from flashing.
    Do

        animate: Locate y, x + 1, 1 ' animation routine is called again here.

        If LCase$(key$) >= "a" And LCase$(key$) <= "z" Or key$ = " " Then
            If x < _Width Then x = x + 1: Locate y, x, 1: Print key$;: x = Pos(0) - 1
        End If
        If key$ = Chr$(8) And x > 10 Then Locate y, x: Print " ";: x = Pos(0) - 2

        keyboard key$

    Loop Until key$ = Chr$(13) Or key$ = Chr$(27)
End Sub

Sub animate ' Flow-through sub-routine.
    Static ii, z
    If Abs(Timer - z) > .25 Then
        z = Timer
        If ii Then Locate 15, ii, 0: Print " "; Else Locate 15, _Width: Print " ";
        ii = ii + 1
        Locate 15, ii, 0: Print Chr$(254);
        If ii = _Width Then ii = 0
    End If
End Sub

Okay, let's pretend that message routine was a full blown word processor of around 8000 lines of code. That would take some hefty planning to make it a flow through routine back to the animation in the main; so a solution is to do as in the code above, make it call the animate routine in both the main and the wp message routine. Of course if it was really just a small program, as above, I would have coded then message routine to flow through to the main. The reason is because a program is easier to understand and debug when the programmer can easily figure out which routine was the calling routine. One call to animate is better than two, in this case.

Pete


RE: Through traffic or no? - JRace - 12-02-2024

If memory serves, the system clock on the TRS-80 Models 1 through 4 were software based, updated by regular CPU interrupts.  That meant that long periods with disabled interrupts, such a writing to cassette tape or floppy disk, could cause the clock to run behind.  Always gotta serve the clock; the story of modern life.

When programming, it's usually easier for me to think in terms of — and keep track of  — the overall project, not subroutines.  I hate having to constantly jump around source code chasing down subs, so my programs are often large, monolithic main functions.  My subroutines tend to be small, simple afterthoughts added to clean up the main.  They're usually called by main and return quickly there.

There's nothing wrong with a "blocking" subroutine which hangs the program briefly while waiting for something, as long as the wait does not frustrate the user or cause other problems, but...
In the world of interactive software, that fall-thru method can be thought of as a form of multitasking, a way of keeping the program moving forward and keeping the user distracted so that small delays don't become annoying.



Speaking of falling through: In a prior life I spent 10 years as a control technician.  My primary job was programming HVAC controllers using a stripped-down version of Pascal which had no looping mechanisms, so every program was fall-thru.  As a program ran it would access the current state of things by reading temp sensors, pressure sensors, etc, then make subtle adjustments to get closer to the program's desired targets (the "setpoints").

(That Pascal variant also had no arrays, which was a major pain in the keester on a couple occasions.)

That version of Pascal did have functions & procedures, which were almost never used.  If a program became large enough to need subs, then the program was split up into two or more simple, single-purpose programs.

Coming as I did from a world of "normal" computer programs, with no prior HVAC experience, it was fun getting to know that system.  The first assignment my boss gave me was to improve the program which ran the building's problematic cooling towers.  The program I submitted was a monstrosity of conditionals testing for every possible good or bad state... something I learned was unnecessary on that system.  That beast of a program worked as intended, but it turned out that the real problem was not a software issue, but a hardware one.  Those control panels had been incorrectly wired since day one!


RE: Through traffic or no? - Pete - 12-02-2024

is Fallthough what we are discussing here? It may be, but I thought it described language differences where in blocks some languages require a 'break' or 'return' while others allow the statements to continue... fallthrough.

I like the term, but I'm not sure if it can also be applied to subroutines.

Pete


RE: Through traffic or no? - JRace - 12-02-2024

Fall-through specifically refers to the behavior of switch...case statement in C, C++, and other languages, where execution will fall through from one case statement to the next unless specifically stopped.  It's an often useful feature which can lead to bugs.

One definition found online: "Fallthrough: when a state machine can move to subsequent states in the same program cycle."
(So fallthrough could also occur in ladder logic, etc.)

When I Google "flow-through" I get pages of results about pilots, airlines, and training.

Flowthrough may be more correct, though personally I consider fall-thru & flow-thru to be equivalent.  But hey, I'm a self-taught hack who makes his own rules and terminology.


RE: Through traffic or no? - Pete - 12-03-2024

My use of 'Flow through' is a made up term, just to help describe what is happening. Likewise, absolutely no formal computer education so when it comes to correct terminology, I often don't know my ASCII from my elbow.

Pete