Viewpoint Systems, Inc.
800 West Metro Park
Rochester, NY 14623
Phone: 585.475.9555
Fax: 585.475.9645
Viewpoint Data Management, LLC.
800 West Metro Park
Rochester, NY 14623
Phone: 585.475.9555
Fax: 585.475.9645
Viewpoint News, Spring 2008LabVIEW is designed to use data flow to manage code execution sequencing. LabVIEW also has inherent multitasking capabilities. A simple example forms from branching a wire into two paths: both paths execute in parallel. Thus, data flow implies multitasking. Another obvious example is two separate while loops on a single block diagram: both run their code in parallel.
This multitasking capability is powerful. And LabVIEW programmers should embrace it. However, almost immediately, a desire arises to communicate between parallel tasks.
What if you want to have one loop monitoring safety I/O while another loop is acquiring and graphing? How can you alert the acquisition loop to a safety alarm? This article illustrates the use of synchronization tools to handle familiar and not-so-familiar ways to coordinate parallel code.
If you read the previous issue of this newsletter, you will already be familiar with one synchronization tool. The Framework example built on Producer/Consumer loops used Queues to synchronize data produced in one loop and consumed in the other.
LabVIEW offers several types of synchronization tools:
(From now on, I’m referring to ‘synchronization’ as ‘sync’ to give my spell checker a rest.)
The general use of each one of these tools is to delay code execution until one or more sections indicate readiness.
For example, the Occurrence, which has been part of LabVIEW for a long time (something like LV 3), enables one section of code to pause and wait on the Occurrence for some other section of code to set the Occurrence.
You could accomplish the same thing yourself by writing some code that polls a Boolean global and loops until the global changes state before allowing the data flow to continue to the remainder of the code. (And, of course, you would need to add code to manage the set and clear properly.)
However, Occurrences and the other sync tools don’t need to be polled since they are event-driven and consume very little CPU usage: your paused code essentially goes to sleep.
The following sections describe the various sync tools.
Note: In this article, I am using LabVIEW version 8.5, so the screen captures in the images below might show slightly different screens and images if you are using a different version.
The sync tools are found in the ‘Programming > Synchronization’ palette

The Occurrence tools are located in the ‘Programming > Synchronization > Occurrences’ palette.

The three operations are Create, Wait, and Set.
An example of usage follows in the 2 block diagrams. The first is the main VI. The Occurrence is created on the left side of the diagram (in the sequence frame). The subVI ‘Occ Example Slave’ is called with the value of the Occurrence passed to it. The main VI then waits on a button press events from the ‘Set’ button. Upon each ‘Set’ event, the Occurrence is set. (The flat sequence structure at the end of execution enables the slave VI to stop when the main is stopped.)

This second block diagram is from the ‘Occ Example Slave’ and contains a loop that simply waits for the Occurrence to be set. When the Occurrence is set, the Message Box appears.

Note that there is no wiring between this loop and the main loop other than the Occurrence value. And, yet, the main VI affects the execution of the slave by forcing the slave to delay execution until the main alerts it via the Occurrence.
Occurrence Options
The ‘Wait on Occurrence’ has a timeout option (defaults to “-1 = wait forever”) as well as an “ignore previous”. What does this mean?
If ignore previous is TRUE and another node has set the occurrence before this function began executing, the function ignores the previous occurrence and waits for another one. When ignore previous is FALSE, the function checks whether another node previously set an occurrence. If so, the function executes. However, the Wait on Occurrence function only processes one occurrence at a time and does not hold multiple previous occurrences in memory. This feature can be useful in startup conditions.
Notifiers are a sophisticated version of Occurrences. In fact, NI recommends that you use these instead of Occurrences. Notifiers are found in the sync palette as shown next.

Notifiers have basic operations for Obtain, Send, Wait, Status, and Destroy. Notifiers have the Timeout and Ignore Previous features similar to Occurrences. They can also be named which allows a Notifier to be found elsewhere in your code without needing a connecting wire. Plus, they can pass data from the producer to the consumer and are thus defined with a data type.
An example of usage follows in the 2 block diagrams. The first is the main VI. The Notifier is created on the left side of the diagram with the name “Demo”. The data type associated with this Notifier is a string. The subVI ‘Notifier Example Slave’ is placed on the main block diagram with nothing wired to it. That’s because the slave VI takes advantage of the fact that the Notifier can be obtained by a lookup from its name. See the slave diagram below for details.
The main VI waits on a button press events from the ‘Set’ button. Upon each ‘Set’ event, the Notifier is set and the string “Set Pressed” is passed. When the main VI is stopped, the Notifier is destroyed. Note the non-default use of the ‘force destroy?’ Boolean. This Boolean must be set TRUE to force the destruction of the Notifier even though it is still in use within the slave VI.

This second block diagram is from the ‘Notifier Example Slave’. Note that the Notifier is obtained with the same operation that creates the Notifier within the main VI (in fact, it’s not really clear which Obtain executes first). The slave loop then simply waits for the Notifier to be set. When the Notifier is set, the Message Box displays the string passed by the Notifier.

Note that there is no wiring between this loop and the main loop. And, yet, the main VI affects the execution of the slave by forcing the slave to delay execution until the main alerts it via the Notifier.
Also note that the use of the global ‘Stop?’ flag is not required here because the ‘Wait on Notification’ will error when the Notifier is destroyed in the main VI.
Notifier Options
The ‘Wait on Notification’ has a timeout option and the ‘ignore previous’ similar to the Occurrence.
If the ‘Wait on Notification’ is used in many places within various block diagrams, all of them will retrieve the same data passed by the ‘Send Notification’ operation. However, if multiple “Send” operations execute prior to a “Wait”, the last data written to a “Send” wins.
Also, the data type in the Obtain operation can be anything available in LabVIEW, such as a cluster, array, or variant. Because of this flexibility, the Notifier is a much improved Occurrence.
Queues pass data between two processes: one process pushes data onto a queue (enqueue) and the other consumes data from the queue (dequeue). The consumer process is delayed until data is available in the queue, making queues a mechanism for synchronization. Note that queues are also called FIFOs (First-in First-out).
LV Queues are similar to multi-element Notifiers. Both provide named “handles” for creation and access, hold arbitrary data types, handle multiple writers, and allow timeout periods before causing an error. Unlike a Notifier, a Queue does not have an ‘ignore previous’ option, because subsequent data pushes are always placed on the Queue (unless the Queue is full).
Queues are found in the sync palette at ‘Programming > Synchronization > Queue Operations’.
Queue Options
The number of elements available in a queue is set when you obtain the queue. By default, this size is unlimited (i.e., the size grows to handle any number of new elements). However, this behavior embodies poor programming practice because an application could die a slow death as memory becomes completely consumed. A better approach sets a nominal queue length and monitors for full queue status. A full queue implies the consumer cannot consume elements as fast as they are pushed by the producing code.
Also, LV Queues have an operation to enqueue data to the front of the Queue, rather the normal back of the queue. Thus, you can create a LIFO (Last-in First-out) queue, which is handy if you want to prioritize Queue elements.
The final two sync tools force code to wait on an event, in contrast to data availability like the Notifier and Queue.
The Semaphore tools are found in the sync palette at ‘Programming> Synchronization > Semaphore’ and the Rendezvous tools are found at ‘Programming > Synchronization > Rendezvous’. The Semaphore palette is shown next.

The Semaphore has the following basic operations: Create, Acquire, Release, and Destroy. The Rendezvous has the following basic operations: Create, Wait, and Destroy.
A Semaphore acts like a 4-way stop sign: multiple sections of code want to go, but the stop signs only allow one car at a time. Some example uses are:
A Rendezvous acts like the leader of a group: the entire group is held back until the leaders finds that every one in the group is ready to move. Some example uses are:
Some examples of these sync tools can be found with the NI Example Finder by using “semaphore” or “rendezvous” in the search tab. For example, the rendezvous example resides at <…\National Instruments\LabVIEW 8.5\examples\general\rendezvous.llb\Rendezvous with SubVIs.vi> and its diagram is shown below.

This example creates a Rendezvous of “group” size equal 3, starts three (User) VIs running in parallel, and destroys the Rendezvous after the ‘stop’ button is pressed. Each User VI executes a task which takes a random amount of time to complete. After the task is complete, the VI loops to get ready for another task.
Initially, all three User VIs run in parallel. When one completes prior to the rest, it waits for all others to complete. Only when all 3 tasks are completed, do any of them start their task again. Then, all 3 begin their next task simultaneously.
Semaphore and Rendezvous Options
These sync tools have the usual timeout and naming options. But, note that the naming option during calls to Create has a flag “return existing” that is different than the Notifier and Queue option of “Create if not found”. The meaning is the same, but the logic is reversed. Using TRUE for Notifier and Queue and FALSE for Semaphore and Rendezvous have the same effect.
These sync tools have an important difference from the Notifier and Queue tools: both have knowledge of the quantity of members. The Semaphore defaults to allowing access to 1 member only, but you can create a Semaphore that will release when there are N members waiting; N is specified at Create. Normal usage of a Rendezvous requires that all N members are available before the Rendezvous releases. As with the Semaphore, N is specified at Create. Rendezvous can be resized after creation, Semaphores cannot.
This article discusses various synchronization tools available in LabVIEW. All these tools delay the execution of one or more parts of code pending some event. For Notifiers and Queues, the event is the availability of data. For Semaphores and Rendezvous, the event is reaching the correct count for members of the associated group achieving the proper condition.
Enjoy!