09-10-2010 10:04 AM
Hi,
I have the following situation (see also attached vi, made with LV2009SP1):
1) one producer that is used as a "commands generator" for the consumer threads
2) three consumers threads, each of them makes a particular task (let's say they checks something, each with different execution time)
How can the producer have the replies (in term of error cluster) from the three parallel threads?
Once I enqueue the command in the queues, each thread can work in parallel, but how can it report back?
Is the producer-consumer a pattern with intrinsic "mono-directional" communication from producer to consumer(s)?
Maybe one solution would be to avoid "producer consumer" and simply put three subVI in parallel, and then collecting their error outputs (with "find first error"). But this solution cannot update the LED controls that I want in the "main" VI.
Any advice would be appreciated.
thanks
09-10-2010 10:22 AM
One method I have used is to have a pair of queues between the producer and each consumer. One carries commands as you have done. The other moves data in the opposite direction to report status, errors, data for the front panel, and so on.
This will also allow you to eliminate your local variables.
Lynn
09-10-2010 10:22 AM - edited 09-10-2010 10:22 AM
There are multiple different ways, but I would create a user event that accepts an error cluster. You can then generate a user event in any loop and the producer will get it.
Edit: similar to lynn's idea above, just using a different method.
09-10-2010 10:25 AM
This seems like a case of choosing the wrong synchronization method. Essentially you have three identical queues triggered at the same time with one command. Using a single Queue with multiple consumers would only work if the command did not dequeue when first read but was garanteed to only be read once for each dequeue function instance. Luckilly there is a function that does do that and you may want to use a Notifier.
The limitation with notifiers though is that you can't really get a "command" just a boolean. So you need to add a FGV. Write the FVG with "Command" just before sending the notifier and let each loop read the FGV each time the notifier is sent and you have some good extensible code.
Stop on first error as a bit trickier. First the for loops need the conditional stop terminal enabled or the MUST complete. And you need to check the error of the current loop and a way to pass error information to the other loops. Time for another FGV! for each loop On error write FGV with the Error cluster (append to an array in case more than one loop errors) and set a boolean in the FGV. Read the FGV in every iteration of every loop and stop if it indicates an error.
09-10-2010 10:35 AM
You might check my Community nugget on events.
I use it as a general purpose design and it can be adjusted to fit your needs.
Felix
09-10-2010 12:08 PM
Here is a rough idea. Use just one queue for producer to consumers direction and one queue for consumers to producer direction. The queue element can be a cluster with one element being the consumer number (1, 2, or 3), and another element being the command. The producer queues up the command with the proper consumer number (use a different number to broadcast to all consumers, like 255). Each consumer previews the queue. When it sees its ID, it dequeues that element. Extra coding is need to handle the broadcast case. Some type of notifier to let the last consumer know to dequeue the broadcasted command.
In the other direction, same principle. Each consumer puts its ID and response in a cluster to be queued. The producer dequeues and acts appropriately.
Upon stop, the loops will have to be written so that they can be interupted at any time so that you don't wait on the slowest loop to complete before shutting down. While loops with a check for the shutdown command, or For Loops with the break condition enabled. For this, maybe a separate notifier could be used.
A wild idea with much coding, but I believe it could be made to work for your purpose. Is it better than having three separate queues (or 6 queues for both directions)? I don't know. It may be worth a try.
09-10-2010 12:25 PM
Another flavor is to pass the messages as clusters, with one element being the destination, another the source, the third the data. The various consumers can do a "preview queue" to see if it is for them, if not don't dequeue the message.
09-10-2010 12:30 PM
@LV_Pro wrote:
Another flavor is to pass the messages as clusters, with one element being the destination, another the source, the third the data. The various consumers can do a "preview queue" to see if it is for them, if not don't dequeue the message.
With the exception of the source element, isn't the rest exactly what I said?
09-10-2010 01:09 PM
@tbob wrote:
.... Is it better than having three separate queues (or 6 queues for both directions)? I don't know. It may be worth a try.
A unique set of queue for each set of interactions works fine for me since they let me deal modularly with each entity. I have delivered multiple apps that used multiple queues, one used more than 300 queues when configured for 100 background processes running (Command_Q, Response_Q, Update_Q).
Ben
09-10-2010 02:07 PM
OpenG contains a Message Queue library.
http://forums.openg.org/index.php?showtopic=991