Knowledge Base

MultiTrack (Basic): The YieldTask instruction

In the previous lesson I showed you how potentially blocking instructions like WaitOn and Pause will automatically cause a task switch, i.e. cause the task to yield so another task can run. But what if there are no such instructions being executed?

The YieldTask instruction lets you force a task switch anywhere you like in your program. This is something you have to think about, for two reasons:

  1. If a task never yields, no other task will get a chance to run.
  2. If a MultiTrack task executes more than 255 instructions without yielding, the controller will suffer a fatal runtime error (we made it that way to force you to do the right thing!)

To illustrate this, copy the following into SPLat/PC and run it:
(Click here for some tips for working around problems with copy and paste out of Internet Explorer and HTML-help (.chm) files)

                LaunchTask  TaskA
                LaunchTask  TaskB
                RunTasksForever

TaskA:          On          0
                Pause       1
                Off         0
                Pause       1
                GoTo        TaskA

TaskB:          IncM        0
                GoTo        TaskB

The program will “bomb out” after a short while. A YieldTask placed after the IncM instruction will allow it to run properly. Try it!

Here’s an example of a task that uses YieldTask. This task will monitor inputs 2 and 3 simultaneously. If input 2 comes on it increments RAM location Count. If input 3 comes on it decrements Count. Having counted up or down it waits for both inputs to be off, then repeats.

CountFunc:       GoIfInOn    2,CountUp
                 GoIfInOn    3,CountDn
                 YieldTask               ;Give someone else a go
                 GoTo        CountFunc   ;Loop and repeat

CountUp:         IncM        Count
                 GoTo        WaitForBothOff

CountDn:         DecM        Count
WaitForBothOff:  YieldTask
                 GoIfInOn    2,WaitForBothOff
                 GoIfInOn    3,WaitForBothOff
                 GoTo        CountFunc
Count:           mEQU        10            ;Declare the RAM variable
			
Exercise 1:

Combine the above task with the dual flasher example in the earlier example and get it running. Take time to study what the YieldTask is doing.

Hint: You can monitor Count at location 10 in the Data Memory window in SPLat/PC (explore the Window menu if this is unfamiliar ground).

Exercise 2:

The first loop of CountFunc (the first 4 instructions) uses one instruction more than necessary. Rearrange it so it only use 3 instructions. Hint: Move the YieldTask to the start of the loop, eliminate the unconditional GoTo and modify the remaining two conditional GoTo‘s so it works. Note: In general you should not stress over minor inefficiencies like this one in your code. In fact, unless you are pushing the limits of available memory, some inefficiencies are a good investment if they make the code easier to read.

Exercise 3:

Consider the following rewritten snippet of code:

WaitForBothOff:  WaitOff     2
                 WaitOff     3
                 GoTo        CountFunc

This would seem to achieve the same result with a saving of 2 lines of code. However, the original will only “trip” when both inputs are off simultaneously. Work out why the the above snippet could “trip” with input 2 on and input 3 off.