LabVIEW Channel Wires

cancel
Showing results for 
Search instead for 
Did you mean: 

Error: Channel Wires Cannot Enter and Leave a Structure

The channel wire was created as a tag channel for a Boolean stop.

Parallel Loops and Channels.png

This was the most intuitive way for me to try and use a stop channel wire to stop multiple loops. The above VI is broken with error:

Error Message.png

If I rewire the diagram like below, the compiler doesn't complain and the VI runs (stops) as expected.

Parallel Loops and Channels_Single Exit.png

but, this doesn't seem any more semanitcally meaningful than my first attempt and seems to put precedence to the middle loop (which I do not intend). Grappling with the error details (specifically the 'meaningless for a channel to pass through a structure'); why is this considered 'passing through' when the subVI has write and read endpoints? Is this a case of overly zealous compiler error checking?

Doug
NI Sound and Vibration
0 Kudos
Message 1 of 13
(12,277 Views)

Having played with Channels some more, and having listened to Jeff K's video, I'd like to suggest that there's an intuitive and error-free way to add a "Multiple Stop" VI based on a Tag.  I've extended DSB's example by adding a "Stop everything on an Error" as well.  All of

the loops "Export" the Stop Signal on their "output" side, where they are joined together.  Single Entry/Exit, and it occurs near the right edge, the "traditional" place for the Stop Indicator.  The Stop sub-VI (to the right, below) is identical to DSB's post.

Stop Multiple Loops.pngStop Tag.png

Bob Schor

P.S. -- if you actually code this and run it, pushing Stop doesn't immediately stop the program as the Error loop needs 5.001 seconds to run.  To really see "instant-stop", diagram-disable the Error demonstration loop.

Message 2 of 13
(10,822 Views)

Your picture looks to my eye identical to what we already have as a shipping example for Sound&Vibration toolkit. What did you modify about the stop VI?

0 Kudos
Message 3 of 13
(10,822 Views)

By the way, we did have to update the Stop VI to prevent a race condition where a False (no error) would overwrite a True. So much for error free.

Stop Channel VI with Conditional Write.png

Stop Channel VI with Conditional Write_FalseCase.png

Doug
NI Sound and Vibration
0 Kudos
Message 4 of 13
(10,822 Views)

Read-modify-write. Ah, tags. 🙂

And this, ladies and gentlement, is why we do not ever use Tags in parallel code. Tags are a bad idea. So why do we have a channel tag? For the same reason that we have global variables... I can't convince the whole planet of the worthlessness of tags. Some people happen to write successful code with tags sometimes... and they think that makes it ok to use them ever. BAH!

I'll be in my ivory tower if anyone needs me.

0 Kudos
Message 5 of 13
(10,822 Views)

Wow -- a Discussion!

AQ -- I didn't see the "shipping example for Sound & Vibration" (haven't used that Toolkit).  I was trying to comment on DSB's earlier post, and tried to duplicate his Stop VI (since it was only a picture, I had to re-create it as best I could, and thought I did it correctly).

DSB -- it's not clear to me why a False would overwrite a True in the code that both you and I posted.  Did you mean that someone could simply "jam" a False into the Tag Channel (as opposed to accessing the Tag Channel only through the Stop VI)?  I think I also did an implementation similar to the one you are showing as an "improvement", but, tyro that I am, I still don't see the problem nor understand why there is a race condition (those can be tricky to spot).

AQ -- I'd like to entice you out of your Ivory Tower (only we Academics are allowed there!) and get you to explain the Problem with Tags.  I really am interested ...

0 Kudos
Message 6 of 13
(10,822 Views)

read-modify-write.

That's all there is to explain about the problem. In a multi threaded world, they are unsafe. They carry no synchronization protection to create protection for any meta operation, so they are entirely dependent upon the programmer realizing that the tags are unsafe and applying that protection. But it gets worse -- that protection, because it is something the programmer has to add, is almost inevitably annoying to code, hard to maintain, has significant performance impact, and is generally screwed up in its implementation by programmers the first time it is done for any given setup.

So programmers don't even realize they need the protection most of the time and once they do, they don't know how to build it, and when they go look up online "how do I protect myself in this situation", they find a plethora of possible solutions, each one unique to its conditions. For example, the case structure fix only works because this is a Boolean whose value latches in one direction (false to true with no reset). If it had to handle arbitrary read-modify-write, like incrementing the value in a numeric tag, then you need a whole different kind of solution. Like making the VI non-reentrant. Which works great... until you need to do multiple operations on the tag, and then you either put all the operations on the same VI (loading up the conpane with every option under the sun), or you have multiple subVIs that access the tag that are surrounded by Semaphore Acquire and Semaphore Release calls. And now you have the problem of communicating that semaphore around! And those are the easy cases. They get worse.

We have not even mentioned the data copy disaster that is tags... every read is a full copy of the value out because a copy of the value has to be left in the tag in case there's some other reader. So a read-modify-write ends up with the same copy overhead as a global VI.

So then someone says, "Well, LV R&D, why don't you make a lockable tag?" And we could... suppose we took the time to put border nodes on the In Place Element Structure where the left node is "Read Tag" and the right node is "Write Tag"... that would cover the data copy and the locking. Great! But I guarantee that users would still forget to use that structure, and those that did would still complain bitterly about having to have this heavy structure thing ... because they already complain about it with the Data Value References. DVRs are just refnums to tags.

Tags are variables. Variables in multithreaded programs are bad. Bad. Bad. And getting worse the more multithreaded and parallel the world becomes. They are a crutch from C and assembly days and they need to be left in the dustbin of history. Period. I have no compromise position on this. I use them sometimes because G doesn't contain all the necessary tools to not use them (getting data from FPGA to host pretty much requires network shared variables, for example). But they are dangerous toys.

Message 7 of 13
(10,822 Views)

Bob_Schor wrote:

I still don't see the problem nor understand why there is a race condition (those can be tricky to spot).

Consider Node A and Node B, both of which are your implementation of the Stop.vi. The user presses the stop button in Loop A.

Because they run in parallel, the order of operations could be:

Node A reads the Tag "FALSE"

Node B reads the Tag "FALSE"

Node A writes the Tag "TRUE"

Node B writes the Tag "FALSE.

So Loop A stops, but Loop B never does because node B never returns true.

0 Kudos
Message 8 of 13
(10,822 Views)

I thought that was the purpose of VIG/FGV "encapsulation".  My Stop VI is not reentrant.  So let's say A and B are running in parallel and the user pushes the Stop button in Loop A.

   Loop A calls Stop VI.  Stop VI is entered, Tag is read as False, Or gate returns Stop Out = True, feedback sets Tag = True.

   While A is doing this, B calls Stop VI.  B can't "get in" because A hasn't yet exited.

   A exits, and B gets into Stop VI.  I was assuming that A setting the Tag = True was "atomic", that A went right to where the value was stored and changed it, so that by the time A exited from Stop VI, any subsequent caller (e.g. B) would see the changed value.  Is this not the case?

   If Stop VI does work like a VIG and changes the Tag before it exits, then when B calls Stop VI, B will read the Tag as True, and All is Well with the World.

I can definitely appreciate that this might not be the case, and thus a significant misperception on my part.  It is interesting how Timing, which I tell my students that LabVIEW treats as an important part of the Language, can sneak in and trip you up!

Bob "Still Learning" Schor

0 Kudos
Message 9 of 13
(10,822 Views)

If it is not reentrant then you do not have this problem. But if it is not reentrant, you are adding more thread friction and having a deliterious performance impact.

For best performance, make the VI reentrant, inline, and add the case structure.

Message 10 of 13
(10,822 Views)