LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How do I explicitly invoke an ancestor of a dynamic dispatch VI

Spoiler
If your instances are shared through DVRs, then a single instance can't be accessed at the same time (assuming the object itself is what's in the DVR and not references inside the object) - the DVR mechanism protects you from that and once you use the IPE structure to access a DVR, any other structure which wants it will have to wait until the first structure is done with it before it can proceed. Thus, setting and unsetting the flag inside the IPES should not cause race conditions.

 

 

 

MF> True. However, two methods of the same instance cannot be inside the same IPES. The race condition occurs after the first thread sets the flag when the second thread gains control of the instance. The second thread will get the value of the flag set by the first thread and perform as if it were the first thread.

 

 

Spoiler
Likewise, if you simply split the class wire you created two separate instances and again there is no race condition (although that doesn't seem to be correct behavior in your case).

 

 

 

MF> True. However, we do not like to create what we call 'clones' of the same resource. The result can be ugly and difficult to debug when multiple threads perform on the same resource without properly managing the resource between the threads.

 

MF> That said, perhaps in this case, with very careful documentation and coding, putting the flag in the child instance data outside of a DVR will achieve the desired result - clientA invokes child.p1 which sets the internal flag; clientB invokes child.m1 (which has it's own unchanged 'copy' of the internal flag), then clinetA's call to child.p1 calls child.m1 which sees the desire for the flagged behavior.

 

 

Spoiler
Note that it might be possible to open an explicit VI server reference to parent.m1 and run it with the CBR node, but I have a vague recollection that if you do that LV will still use the DD mechaism to run child.m1. This will probably not happen if you use the Set Ctl Val and Run VI methods, but that workaround is so bad it hurts me just to type it.

 

 

 

MF> I too believe that it will do the CBR.

0 Kudos
Message 11 of 24
(885 Views)

Sorry about those spoiler tags. Not sure what I was thinking.

0 Kudos
Message 12 of 24
(883 Views)

Then maybe I'm misunderstanding what you have or you're misundersanding what we're suggesting. I see no reason why you would need careful documentation or protection. What I'm thinking of should be completely safe and the setting and unsetting are local to a single VI, so that only the person developing the child class has to be careful about getting it right, but they only have to do that once, so they wouldn't have to be any more careful than with any other code.

 

Maybe you can upload a concrete example (back saving it to 2009 or 2011 would be nice) so we have a proper base for discussion? I didn't look at the original, but the image there doesn't show any DVRs.


___________________
Try to take over the world!
0 Kudos
Message 13 of 24
(864 Views)

Attached is an updated LV2011 version using DVRs with what I was hoping would work.

The Parent class manages the 'value', and the Child class enhances the Parent class with protection so that a client can only change the value if it is not locked.

0 Kudos
Message 14 of 24
(855 Views)

Please note, the Child.setValueLocked has the same signature in this as Child.setValue and Parent.setValue. However, the setValueLocked is meant to have other controls.

0 Kudos
Message 15 of 24
(852 Views)

Cant you simply drag in the parent function and call it?

In this snippet TestChild is a child of TestClass and this function calls TestClass:Start as part of the function (class names can be seen in vi header). Or is that a unique feature of G#?

/Y

 

ClassSnippet.png

G# - Award winning reference based OOP for LV, for free! - Qestit VIPM GitHub

Qestit Systems
Certified-LabVIEW-Developer
0 Kudos
Message 16 of 24
(839 Views)

This is different than what you descbried earlier. My understanding was that you wanted an unconditional call to the parent, and that should be as simple as this, which is what we were describing. As you can see, that should be pretty safe:

 

Child.lvclass_setValueLocked_BD.png

 

 

I'm not sure what the locking behavior you want is exactly. In your example, I see that you're returning an error if there's a lock, but you're right that using a DVR like that can lead to race conditions. I think that you can also considerably simplify this if you're willing to change the behavior to have a lock actually hold the VI until the DVR is available -

 

Child.lvclass_setValue_BD.png

 

This will simply cause a proper lock - each call to child.set value will have to wait if there's already another child.set value in progress. Note that this has nothing to do with the caller and that the value of the lock is actually meaningless - the DVR itself is what's used as the locking mechanism, not the value in the DVR.

 

If this behavior is not good, then don't use a DVR - instead use another locking mechaism which has a timeout. A good example would be a single element queue - start with a dequeue with timeout 0. If it timed out, don't execute the call. If it didn't, you locked the queue and you can make the call and then reenqueue, which will unlock.


___________________
Try to take over the world!
0 Kudos
Message 17 of 24
(838 Views)

Yes, this is the implementation pattern that I will be going with. The Child.CallParent attribute needs to be carefully managed and documented because it lives on the wire (rather than in the DVR) and a 'true' value should not be allowed to be returned to the caller.

 

The recent example I provided was how I expected/hope it would work - when the cast to the Parent class was performed in Child.setValueLocked, I expected Parent.setValueto be called, but it wasn't.

 

The requirements I am implementing to require that if the lock is set, an error is returned to other callers into the instance until the lock is cleared.

0 Kudos
Message 18 of 24
(821 Views)

Here is an update to the example, that works.

When main.vi is run, notice that the 'Child casted to Parent.setValue' and 'Child.setValue' test steps (in the main.vi) will either succeed or fail (busy) as they are racing with the 'Child.setValueLocked' step which are all executing in parallel.

0 Kudos
Message 19 of 24
(817 Views)

It seems to me that you're over-complicating things for no reason. You have two locking mechanisms, which doesn't seem to help, and frankly I don't understand the code.

 

I would say that the easiest thing would simply be to make all the DD VIs non-reentrant. This will guarantee a simple lock. If that's no good for you and you want the child class to guarantee a lock (because apparently that's its stated goal), then I would suggest using the second example I showed above - wrap the call to the parent in an IPES.

 

If you still want the behavior where a locked object returns an error, do the same thing, but replace the DVR with a queue or a semaphore, like so:

 

Child.lvclass_setValue_BD.png

 

Much simpler and much easier to understand - if you couldn't get a lock (i.e. a timeout), return an error. Otherwise, call the parent and unlock. There's absolutely no need for the calling VI - the code shown here should be all that you need.


___________________
Try to take over the world!
0 Kudos
Message 20 of 24
(795 Views)