The Master/Slave design pattern is another fundamental architecture LabVIEW developers use. It is used when you have two or more processes that need to run simultaneously and continuously but at different rates. If these processes run in a single loop, severe timing issues can occur. These timing issues occur when one part of the loop takes longer to execute than expected. If this happens, the remaining sections in the loop get delayed. The Master/Slave pattern consists of multiple parallel loops. Each of the loops may execute tasks at different rates. Of these parallel loops, one loop acts as the master and the others act as slaves. The master loop controls all of the slave loops, and communicates with them using messaging architectures.
The Master/Slave pattern is most commonly used when responding to user interface controls while collecting data simultaneously. Suppose you want to write an application that measures and logs a slowly changing voltage once every five seconds. It acquires a waveform from a transmission line and displays it on a graph every 100ms, and also provides a user interface that allows the user to change parameters for each acquisition.
The Master/Slave design pattern is well suited for this application. In this application, the master loop will contain the user interface. The voltage acquisition and logging will happen in one slave loop, while the transmission line acquisition and graphing will happen in another.
Applications that involve control also benefit from the use of Master/Slave design patterns. An example is a user’s interaction with a free motion robotic arm. This type of application is extremely control oriented because of the physical damage to the arm or surroundings that might occur if control is mishandled. For instance, if the user instructs the arm to stop its downward motion, but the program is occupied with the arm swivel control, the robotic arm might collide with the support platform. This situation can be avoided by applying the Master/Slave design pattern to the application. In this case, the user interface will be handled by the master loop, and every controllable section of the robotic arm will have its own slave loop. Using this method, each controllable section of the arm will have its own loop, and therefore, its own piece of processing time.
This will allow for more responsive control over the robotic arm via the user interface.
Why Use Master/Slave?
The Master/Slave design pattern is very advantageous when creating multi-task applications. It gives you a more modular approach to application development because of its multi-loop functionality, but most importantly, it gives you more control of your application’s time management. In LabVIEW, each parallel loop is treated as a separate task or thread. A thread is defined as a part of a program that can execute independently of other parts. If you have an application that doesn’t use separate threads, that application is interpreted by the system as one thread. When you split your application up into multiple threads, they each share processing time equally with each other.
This gives you more control on how your application is timed, and gives the user more control over your application. The parallel nature of LabVIEW lends itself towards the implementation of the Master/Slave design pattern.
For data acquisition example above, we could have conceivably put both the voltage measurement and the waveform acquisition together in one loop, and only perform the voltage measurement on every 50th iteration of the loop. However, the voltage measurement and logging the data to disk may take longer to complete than the single acquisition and display of the waveform. If this is the case, then the next iteration of the waveform acquisition will be delayed, since it cannot begin before all of the code in the previous iteration completes. Additionally, this architecture would make it difficult to change the rate at which waveforms were acquired without changing the rate of logging the voltage to disk.
The standard Master/Slave design pattern approach for this application would be to put the acquisition processes into two separate loops (slave loops), both driven by a master loop that polls the user interface (UI) controls to see if the parameters have been changed. To communicate with the slave loops, the master loop writes to local variables. This will ensure that each acquisition process will not affect the other, and that any delays caused by the user interface (for example, bringing up a dialog) will not delay any iteration of the acquisition processes.