Jump to content

LabVIEW OOP By Ref?


Recommended Posts

So I thought that if the class just holds the DVR of the datamembers then I get dynamic dispatch without any fuss and I have a reference to my datamembers giving in effect a object that has by ref characteristics.

Hi Kurt,

I've been looking at your example reference classes (Bike+Racer) and I'm starting to second-guess my decision about wanting to put the DVR outside the object (rather than put the DVR inside the object). :blink:

I how your example (DVR inside the object) allows dynamic dispatch at the public method level (instead of having a static, by reference method that wraps a protected, dynamic, by value method -- this creates a lot of extra methods).

However, one thing that makes me uneasy about putting the DVR inside the object (as your example does) is that each level of the inheritance hierarchy has it's own DVR and is locked/unlocked separately. I worry that this could cause some nasty race conditions or deadlock -- have you thought about this? And, an attempt to remedy this issue takes us back to where we have a lot of framework/support VIs for each class.

Cheers,

Link to comment

However, one thing that makes me uneasy about putting the DVR inside the object (as your example does) is that each level of the inheritance hierarchy has it's own DVR and is locked/unlocked separately. I worry that this could cause some nasty race conditions or deadlock -- have you thought about this? And, an attempt to remedy this issue takes us back to where we have a lot of framework/support VIs for each class.

Cheers,

Hey Jim

That's a good point that I haven't explored deeply. My first thought is that class Bike has its own DVR to it's datamembers and the child Racer has its own so they are separate and shouldn't interfere with each other. I'll do some tests and see what is involved in breaking it or causing it to lock.

Link to comment

Hey Jim

That's a good point that I haven't explored deeply. My first thought is that class Bike has its own DVR to it's datamembers and the child Racer has its own so they are separate and shouldn't interfere with each other. I'll do some tests and see what is involved in breaking it or causing it to lock.

Talk to Mikael... putting the DVR inside the class sounds an awful lot like the GOOP Toolkit implementation where they wrap a raw reference to data in a class to give it dispatching behaviors. Mikael may have some info about the deadlock potential of this situation.
Link to comment

Talk to Mikael... putting the DVR inside the class sounds an awful lot like the GOOP Toolkit implementation where they wrap a raw reference to data in a class to give it dispatching behaviors. Mikael may have some info about the deadlock potential of this situation.

We had a beer together last week and realized that we had both come to the same solution. Perhaps we can put our heads together again on this one.

Link to comment
  • 3 weeks later...

However, one thing that makes me uneasy about putting the DVR inside the object (as your example does) is that each level of the inheritance hierarchy has it's own DVR and is locked/unlocked separately. I worry that this could cause some nasty race conditions or deadlock -- have you thought about this? And, an attempt to remedy this issue takes us back to where we have a lot of framework/support VIs for each class.

Cheers,

I've been having another play with the concept of datamember DVR inside object ref and it’s appearing to be solid.

The only thing you need to watch is that you don't perform a method call inside an In Place Structure DVR R/W that acts on the same data. So placing a method of the same class or a parent method with dynamic dispatch will cause it to lock. Placing a parent only method inside a child method's InPlace Structure DVR R/W is OK since it only acts on the parent data which has its own DVR. But in the end it’s the same kind of rules you would use as before when you had lock and unlock primitives in previous architectures.

I haven’t been able to create a race condition as a result of implementing parent and child data member DVR’s. Since parent data is accessed in a child by parent methods the data is protected, the data locking protection mechanism exists at all levels of the object hierarchy.

Link to comment

I've been having another play with the concept of datamember DVR inside object ref and it’s appearing to be solid.

The only thing you need to watch is that you don't perform a method call inside an In Place Structure DVR R/W that acts on the same data. So placing a method of the same class or a parent method with dynamic dispatch will cause it to lock. Placing a parent only method inside a child method's InPlace Structure DVR R/W is OK since it only acts on the parent data which has its own DVR. But in the end it’s the same kind of rules you would use as before when you had lock and unlock primitives in previous architectures.

I haven’t been able to create a race condition as a result of implementing parent and child data member DVR’s. Since parent data is accessed in a child by parent methods the data is protected, the data locking protection mechanism exists at all levels of the object hierarchy.

Thanks for the update. I too have seen the lockup. It can be not-so-obvious too. That is, you could call what appears to be a parent method that then calls a dynamic dispatch method that ends up attempting to access the same DVR you started in. Hope that was clear wacko.gif .

All in all, I am finding this a very sweet way to implement objects as references yet still allow me to have dynamic dispatch work. I am still expecting to find a 'gotcha', but for now I am enjoying the feature.

I have modified daklu's DVR Composition project such that it implements the member vars as a DVR of a cluster. The original DVR Composition project primarily showed an approach to facilitate Interfaces and Implementations by using DVR's of objects. The addition of DVR member variables eliminated the IPE structures from the general application code seen in Main.vi and reduced the casting that was used inside the IPE of the Multiply By Two Implementation. I hope to post this soon with some screen shots. My biggest problem is that my development machine is not on the network and my network machine is restricted to have only certain applications. So the transfer is just one more hurdle.

Between your scheme of DVR'd member variables and daklu's Interface/Implementation work, this solved a huge problem I was having in my project. I also plan on posting some of this too. I am a bit restricted on what my employer will allow me to publish nono.gif .

Link to comment

I've been having another play with the concept of datamember DVR inside object ref and it’s appearing to be solid.

The only thing you need to watch is that you don't perform a method call inside an In Place Structure DVR R/W that acts on the same data. So placing a method of the same class or a parent method with dynamic dispatch will cause it to lock. Placing a parent only method inside a child method's InPlace Structure DVR R/W is OK since it only acts on the parent data which has its own DVR. But in the end it’s the same kind of rules you would use as before when you had lock and unlock primitives in previous architectures.

I haven’t been able to create a race condition as a result of implementing parent and child data member DVR’s. Since parent data is accessed in a child by parent methods the data is protected, the data locking protection mechanism exists at all levels of the object hierarchy.

Hi Kurt,

I'm happy to hear you say this, since I've come to the same conclusion while talking it over with other members of my team. IMO, the value of being able to Dyamic Dispatch any method, regardless of whether it's a by value or by reference method, without having to create special, duplicate by reference wrapper methods around dynamic by value methods is huge.

The only downsides (that I can see) of using the DVR inside an LVOOP object are:

1) You can't tell just by looking an an object that it's by reference (as you can when you see a DVR with an LVOOP object inside)

2) You have to unbundle the DVR before you can pass it into a IPE Structure

Oh, and there's one situation that you also have to be very careful for:

If you're inside a child method and you call a parent method inside an IPE structure, you might deadlock if the the parent method is itself, or calls inside of it, a dynamic dispatch method that results in child method being called.

With this in mind, one feature that I'd love to see in LabVIEW is for IPE structures to be smart at run-time and output an error (rather than deadlock) if an IPE is called inside another IPE and tries to dereference data that has already been dereferenced by the outer IPE.

Cheers!

Thanks for the update. I too have seen the lockup. It can be not-so-obvious too. That is, you could call what appears to be a parent method that then calls a dynamic dispatch method that ends up attempting to access the same DVR you started in. Hope that was clear wacko.gif .

All in all, I am finding this a very sweet way to implement objects as references yet still allow me to have dynamic dispatch work. I am still expecting to find a 'gotcha', but for now I am enjoying the feature.

I have modified daklu's DVR Composition project such that it implements the member vars as a DVR of a cluster. The original DVR Composition project primarily showed an approach to facilitate Interfaces and Implementations by using DVR's of objects. The addition of DVR member variables eliminated the IPE structures from the general application code seen in Main.vi and reduced the casting that was used inside the IPE of the Multiply By Two Implementation. I hope to post this soon with some screen shots. My biggest problem is that my development machine is not on the network and my network machine is restricted to have only certain applications. So the transfer is just one more hurdle.

Between your scheme of DVR'd member variables and daklu's Interface/Implementation work, this solved a huge problem I was having in my project. I also plan on posting some of this too. I am a bit restricted on what my employer will allow me to publish nono.gif .

I see that you posted similar thoughts, just as I was typing up my reply to Kurt, above :)

Cool! It seems that we're all starting to converge on the preferred methodology (pun appreciated but not intended) for by ref OOP in LV2009.

I guess that I would add that if NI were to implement either the ability to dynamic dispatch on methods with DVRs of objects OR the ability to wire a DVR of an object into a by value method (dereferencing/referencing behind the scenes) then I would probably migrate over to DVRs containing objects, rather than vice versa. But, until then...

Link to comment

Hi Kurt,

I'm happy to hear you say this, since I've come to the same conclusion while talking it over with other members of my team. IMO, the value of being able to Dyamic Dispatch any method, regardless of whether it's a by value or by reference method, without having to create special, duplicate by reference wrapper methods around dynamic by value methods is huge.

The only downsides (that I can see) of using the DVR inside an LVOOP object are:

1) You can't tell just by looking an an object that it's by reference (as you can when you see a DVR with an LVOOP object inside)

2) You have to unbundle the DVR before you can pass it into a IPE Structure

Oh, and there's one situation that you also have to be very careful for:

If you're inside a child method and you call a parent method inside an IPE structure, you might deadlock if the the parent method is itself, or calls inside of it, a dynamic dispatch method that results in child method being called.

With this in mind, one feature that I'd love to see in LabVIEW is for IPE structures to be smart at run-time and output an error (rather than deadlock) if an IPE is called inside another IPE and tries to dereference data that has already been dereferenced by the outer IPE.

Cheers!

I see that you posted similar thoughts, just as I was typing up my reply to Kurt, above smile.gif

Cool! It seems that we're all starting to converge on the preferred methodology (pun appreciated but not intended) for by ref OOP in LV2009.

I guess that I would add that if NI were to implement either the ability to dynamic dispatch on methods with DVRs of objects OR the ability to wire a DVR of an object into a by value method (dereferencing/referencing behind the scenes) then I would probably migrate over to DVRs containing objects, rather than vice versa. But, until then...

SciWare and I have the same first name (yes, with a K), so it was funny to read your first reply as if you were talking to me. I agree with you on all of your points. Your downside point #1 (not knowing if class's data is inside a DVR) is rather critical too. It is very dissapointing to use a class as if its data was inside a DVR and find out that it does not. My solution is to have all of my classes support this concept. I am not sure how painful this is going to be in the long run as my project is in the early stages. I am essentially a one man show on the LVOOP front at my company. My colleagues have lots of LV experience but little OOP. I came on board earlier this year with the oppposite. This forum has been a life saver!

Anyway, this extra work is a nuisance and I would rather migrate to an NI implementation.

Link to comment

SciWare and I have the same first name (yes, with a K), so it was funny to read your first reply as if you were talking to me. I agree with you on all of your points. Your downside point #1 (not knowing if class's data is inside a DVR) is rather critical too. It is very dissapointing to use a class as if its data was inside a DVR and find out that it does not. My solution is to have all of my classes support this concept. I am not sure how painful this is going to be in the long run as my project is in the early stages. I am essentially a one man show on the LVOOP front at my company. My colleagues have lots of LV experience but little OOP. I came on board earlier this year with the oppposite. This forum has been a life saver!

Anyway, this extra work is a nuisance and I would rather migrate to an NI implementation.

Two more disadvantages of DVR's data members:

1)DEBUGGING: With DVR'd data members, when you look at an object, all you see is the reference number. This is certainly true for DVR'd objects as well, but perhaps you would be in a IPE more often than just the Read/Write accessor methods.

2)Flattten to XML: Here too all you get is the reference number of the data. Not surprising, just dissapointing.

Even with these two additions, I am not swayed until NI comes out with something to help.

Link to comment

Between your scheme of DVR'd member variables and daklu's Interface/Implementation work, this solved a huge problem I was having in my project. I also plan on posting some of this too. I am a bit restricted on what my employer will allow me to publish nono.gif .

Cool, I'd love to see some OOP frameworks, would be great to have a bit of a community effort on this.

The only downsides (that I can see) of using the DVR inside an LVOOP object are:

1) You can't tell just by looking an an object that it's by reference (as you can when you see a DVR with an LVOOP object inside)

2) You have to unbundle the DVR before you can pass it into a IPE Structure

Good points, would be useful to see at a glance that your object is by ref, but I suppose we are using by value objects in a by ref capability. Perhaps a convention could be started by choosing a specific wire color, I'd suggest a green color which is consistent with other by ref implementations such as File IO, VI Server, control refs.

Yes, unbundleing all the time is an overhead and takes up a bit of real estate. At the moment I'm also placing a few more items in the object data other than just the datamember DVR to achieve active objects so its usefull to unbundle and get what I need. It would be nice to just plug the object into the IPE but then how does it know what to unpick since the object can hold many things, multiple DVR's possibly

Oh, and there's one situation that you also have to be very careful for:

Ifyou're inside a child method and you call a parent method inside an IPEstructure, you might deadlock if the the parent method is itself, orcalls inside of it, a dynamic dispatch method that results in childmethod being called.

With this in mind, one feature that I'dlove to see in LabVIEW is for IPE structures to be smart at run-time and output an error (rather than deadlock) if an IPE is called inside another IPE and tries to dereference data that has already beendereferenced by the outer IPE.

Ahh, yes, that would get you. At the moment I'm carefull about placing methods inside an IPE unless I have to. If I dont I just use them outside. I agree with you that there needs to be some checking that looks at the method you place and does a check to see if there is any possibility of cycling back to a read on the same DVR

Two more disadvantages of DVR's data members:

1)DEBUGGING: With DVR'd data members, when you look at an object, all you see is the reference number. This is certainly true for DVR'd objects as well, but perhaps you would be in a IPE more often than just the Read/Write accessor methods.

2)Flattten to XML: Here too all you get is the reference number of the data. Not surprising, just dissapointing.

Even with these two additions, I am not swayed until NI comes out with something to help.

A probe on the DVR to show the data would be handy, I suppose the probe would have to implement an IPE behind the scenes and then I can see a situation where you probe your object within and existing IPE and then you get a lockup. I suppose you could make your own custom probe that is a member of your class, a bit like the old object explorer.

I'm really happy that everyone is on the same page with respect to implementing by ref objects. Looks like we have a great kickoff point with a workable framework that is easy to implement and doesn't require a heap of support vi's. In the past I've always used my own OOP implementation to give me what I want because LVOOP just wasn't there yet, but now it is and I'm very happy and I have to say a big thank you to NI for working on this :thumbup1:

Link to comment

Jim Kring wrote:

1) You can't tell just by looking an an object that it's by reference(as you can when you see a DVR with an LVOOP object inside)

Strong recommendation we've developed over the last few years: If your object contains even a single refnum, make the wire color be refnum green. I even updated the color picker in LabVIEW 2009 so that refnum green is one of the default colors displayed so it is easy to grab it for your wire designs (it's the last non-gray square in the row of pre-selected colors).

Also, I've had a few people suggest that if one member of your private data control is a refnum then all of them should be refnums, so that everything in the object behaves like a reference. I'm not sure what I think of that, but I'll throw it out there for consideration.

With this in mind, one feature that I'd love to see in LabVIEW is for IPE structures to be smart at run-time and output an error (rather than deadlock) if an IPE is called inside another IPE and tries to dereference data that has already been dereferenced by the outer IPE.
Unfortunately, the bookkeeping on this is significantly problematic. Essentially, you'd need the inside of the IPE to output an array of refnums that are "the refnums I currently have deref'd" and then pass that by dataflow to any nested (including inside subVIs) IPEs. But the subVIs don't have magic secret inputs/outputs that would allow this information to pass along, and trying to do it in a "global store that each IPE checks to see if refnum was used upstream" requires the IPE to know aspects of dataflow that are simply unknowable, such as what nodes are upstream of it. We did kick around embedding the information in the refnum wire itself, but with a reference, there's no guarantee that the reference is used in only one place.

In the end, we couldn't find a way for the IPE to tell the difference between a refnum that was dereferenced upstream (and should error) and dereferenced in parallel (that will eventually be released), except in the most trivial of cases. If you're writing circular reference code, you'll need to carry along with the refnum a parallel array of refnums already opened, and at every IPE, manually check whether the chosen refnum is already referenced.

  • Like 1
Link to comment

Also, I've had a few people suggest that if one member of your private data control is a refnum then all of them should be refnums, so that everything in the object behaves like a reference. I'm not sure what I think of that, but I'll throw it out there for consideration.

I really like to be able to have both byRef and byValue within the same class.That way I can have a number of high speed access members, and still beable to use ByRef on data that need it. So please don't force peopleinto selecting one type or the other.

/J

Link to comment

I really like to be able to have both byRef and byValue within the same class.That way I can have a number of high speed access members, and still beable to use ByRef on data that need it. So please don't force peopleinto selecting one type or the other.

It's definitely not something I would force ever. It's just a recommendation that a couple folks think should be followed. I've had multiple situations where the mixture was useful, and haven't seen any negatives yet, myself.
Link to comment

One thing that I've started doing with the DVR-inside-LVOOP scheme is using an IPE Structure to (un)bundle the DVR reference outside of the IPE that (de)references the private data. I like this a lot because it keeps the object/reference/data wire in straight line without any branching -- it seems to have the best "style". Note that I named the DVR "ref" to keep the (un)bundle nodes small in width.

What do you think?

post-17-125304052438_thumb.png

  • Like 1
Link to comment

One thing that I've started doing with the DVR-inside-LVOOP scheme is using an IPE Structure to (un)bundle the DVR reference outside of the IPE that (de)references the private data. I like this a lot because it keeps the object/reference/data wire in straight line without any branching -- it seems to have the best "style". Note that I named the DVR "ref" to keep the (un)bundle nodes small in width.

What do you think?

post-17-125304052438_thumb.png

That is nice and neat, I like it.

  • Like 1
Link to comment

One thing that I've started doing with the DVR-inside-LVOOP scheme is using an IPE Structure to (un)bundle the DVR reference outside of the IPE that (de)references the private data. I like this a lot because it keeps the object/reference/data wire in straight line without any branching -- it seems to have the best "style". Note that I named the DVR "ref" to keep the (un)bundle nodes small in width.

What do you think?

post-17-125304052438_thumb.png

I also like the look of that.

Does anyone have a basic example of DVR LVOOP object?

  • Like 1
Link to comment

One thing that I've started doing with the DVR-inside-LVOOP scheme is using an IPE Structure to (un)bundle the DVR reference outside of the IPE that (de)references the private data. I like this a lot because it keeps the object/reference/data wire in straight line without any branching -- it seems to have the best "style". Note that I named the DVR "ref" to keep the (un)bundle nodes small in width.

What do you think?

post-17-125304052438_thumb.png

Looks nice - I frequently do the same thing - using the IPE structure more for style than its pure function - it is a lot less messy than index array followed by wiring the original array and the desired index across the code to the Replace Element function.

Shaun

  • Like 1
Link to comment

Hello All!

This may be a stupid question and not the place to ask it and I did do a rudimentary (but possible not sufficient) search, but where does one find a data value reference constant on the control palette? I am thinking specifically about the situation of creating a class similar to the one contained in the project by SciWare:

In attempting to create my own class with a DVR member, I ran into the problem of where to get the DVR control to place in my strict type definition. It's not in the refnum palette, as I would have suspected and typing "Data Value Reference" in QuickDrop is similarly unsuccessful. My only options were either to copy DataRef.ctl fromthe above project to my own lvclass and change the contained element to my own type or to create a new VI, place a New Data Value Reference primitive on the block diagram, create a constant on its DVR output terminal and drag that to my custom control.

What am I missing?

Thanks in advance!

Brandon

Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.