LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

how should I use semaphore?

I have 2 devices with serial port (Device1 uses COM1, Device2 uses COM2).

On the device level I created bunch of VIs - one VI per serial port command. All device level VIs use "WriteToSerialPort.vi" or/and "ReadFromSerialPort.vi"

Top level VI of program has 2 loops. One loop supports UI controls actions and calls device level VIs. Another loop reads from the devices (also uses device level VIs) some parameters constantly and renew according UI indicators.

 

Sometimes I had that loop1 reads answer after command of the loop2.

I made "WriteToAndReadFromSerialPort.vi" and used semaphore to avoid this problem. But I lost that "2 loops of the program send commands to different devices at the same time".

 

So how can I write program that

- 2 loops of the program send commands to different devices at the same time and don't touch each other answers

- 2 loops of the program can't send commands to the same device at the same time.

 

I know how I can do that in normal language, like C++, C#, or Java. But I can't understand this from LabVIEW manual.

Thanks!

 

Also I am not sure what is mean "task" in semaphore according help. Is loop in my program task?

0 Kudos
Message 1 of 15
(14,148 Views)

Have you taken a look at the semaphores example that ships with LabVIEW?

 

I don't quite understand which "task" input you are referring to. There are no "task" inputs on the semaphore VIs.

0 Kudos
Message 2 of 15
(14,136 Views)
  1. A task, in this context, is any piece of code which uses the semaphore to synchronize.
  2. You need to make the VI reentrant to allow it to execute in parallel.
  3. You need one semaphore for each port. You can name the semaphores to make the access easier.

The simplest solution is to call the obtain VI in each call, but this will leak 4 bytes each time if you don't release the reference and will have some performance implications if you do (although I'm not sure how much.

 

One easy way of working around this is to do something like this:

 

RW Lock.png

 

This obtains the reference once for each copy of the VI in the diagram and then gets it from the feedback node for every subsequent run, but the main problem with it is that assumes that every call of that instance on the diagram will be to the same port. This is a problem if you're not aware of this or if you're iterating over multiple ports in a loop, but there is a solution - you create a manager VI which accepts a VISA ref and returns the appropriate semaphore. Such a VI is non-reentrant and has a global internal buffer of VISA-semaphore pairs which it keeps track of:

 

Sem Glob.png

 

 

If it finds the semaphore in the list, it validates it and outputs it. If not (or it's invalid), it creates a new one and adds it to the list.

 

In this example, I used variant attributes to hold the name-value pairs, but you could also manage it by building two arrays and doing the lookup yourself or by any other method.

 

You can find more info on this type of construct here - http://forums.ni.com/t5/LabVIEW/Community-Nugget-4-08-2007-Action-Engines/m-p/503801#M240328


___________________
Try to take over the world!
Message 3 of 15
(14,114 Views)

smercurio_fc, please, read LabVIEW help about semaphore and you will find "task" word there.

0 Kudos
Message 4 of 15
(14,089 Views)

tst - thanks!!!

I think reentrant VI should work. I would prefer to create structure with serial port and semaphore instead of your second VI.

0 Kudos
Message 5 of 15
(14,083 Views)

 


@Vasilich2004 wrote:

@smercurio_fc, please, read LabVIEW help about semaphore and you will find "task" word there.


I thought you were referring to an input called task.

 

0 Kudos
Message 6 of 15
(14,076 Views)

Think of a task as being how many concurrent things you want to happen at once before they any more are locked out.  In probably 99% of the use cases, you are protecting a section of code so that only one "task" can access it at once.  To go with the train metaphor, let's say you have a single track and potentially multiple trains possibly trying to run down it at the same time.  You'd set the size input to 1.  Let's say you have two parallel tracks.  You'd want to allow up to two trains to run at once, but the third or more trains have to wait until at least one clears, then you'd set the size input to 2.

0 Kudos
Message 7 of 15
(14,060 Views)

Ravens Fan

 

Thank you. I know about normal theory.

But what is "task" mean in LabVIEW? LabVIEW help index doesn't provide reasonable information. It points to DAQmx task!

 

For example, how does LabVIEW work if VI has two independent "lines"? It will create 2 buffers and puts commands from each line and then one real thread will implement comand from one buffer, then from another and so one. Or it will create another real thread for second "line"?

What is rule if the same VI is called from both "lines" at "like" the same time?

0 Kudos
Message 8 of 15
(14,052 Views)

I think the term "task" used in the help file for the semaphore is a little bit ambiguous and certainly isn't the same as tasks for DAQmx.

 

I think the way they are using "task" as a general term in the help file just to say, "Hey, I have two different sections of code that each have something they want to do  (i.e. a job, a task, a series of program functions) that I don't want them to do simultaneously."

 

In your description, I think using the term "buffers" and "lines" is just confusing things more in trying to describe semaphores, and I don't know how to answer you specific questions.  All I can say is that if two different sections of code hit their respective semaphore gates at the same time, one or the other is going to get the lock first and will be able to move on, the code execution is going to pause for the other one.  Once the first "task" gets done its execution and hits the release semaphore block, the semaphore is now released and the second series of code is now free to move beyond the lock semaphore function.  It will lock the semaphore and move on to the following functions.

0 Kudos
Message 9 of 15
(14,040 Views)

 

Task is not a technical term. It just means a piece of code which uses the semaphore.

Vasilich2004 wrote:

 

For example, how does LabVIEW work if VI has two independent "lines"? It will create 2 buffers and puts commands from each line and then one real thread will implement comand from one buffer, then from another and so one. Or it will create another real thread for second "line"?

What is rule if the same VI is called from both "lines" at "like" the same time?


 

The way LV executes parallel code changes based on the compiler version and specific conditions, so there's no way of providing a definitive answer, but in general, if you have two pieces of code which do not have a dataflow dependency, LV will try to execute them in parallel. If you want to dig into the LV execution engine, there are various documents available online.

 

As for the second questions, if the VI is non-reentrant, one instance will have to wait until the other finishes executing. If it's reentrant, you'll get two copies running in parallel.


___________________
Try to take over the world!
0 Kudos
Message 10 of 15
(14,030 Views)