LabVIEW

cancel
Showing results for 
Search instead for 
Did you mean: 

How to track child instances in parent class

I have a **simple** design question about a good way to implement LV OO.

 

I have a parent class (multiple instances) with a single child class. The parent class needs to keep track of all "active" instances of the child class because some parent methods must be applied to all children. Is there a way for this to happen automatically in LV? I'm not aware of any, so I assume I will have to use some "register" and "unregister" actions for creation and destruction of child class instances. But how do I track them; where do I store the list?

 

It would be easiest to simply add an array of child class references to the private class data of the parent. However, LV seems to not support this due to "circular referencing". I am not familiar enough with OO, nor it's implementation in LV to know what is a good design approach to accomplish this task.

 

Any suggestions?

0 Kudos
Message 1 of 22
(3,395 Views)

To be a little more clear:

 

I have 1 parent class and 1 child class. Each instance of child belongs to exactly 1 instance of parent, and cannot exist on its own. Each parent has 0 or more instances of child class that belong to that unique instance of parent. My issue is the runtime tracking of the child instances by the parent... it seems logical to keep a "list" of children in the parent class data, since each parent instance has a unique set of children (or no children). I am unable to include an array of child class references in the class data of the parent due to LV limitations.

 

Have I artificially introduced this limitation? Is there a property setting for the parent or child class that will allow the arrangement I seek?

 

I will see if my collaborator can help with a schematic of the issue.

0 Kudos
Message 2 of 22
(3,383 Views)

Your thinking seems perfectly logical to me. I had a similar problem a while back, got fed up with this limitation of LabVIEW and basically created two individual classes that were almost identical so I could reference one from t'other. Bad coding I know, but it solved an irritating problem that need fixing sharp.

 

You could try some options like converting the child references to variants before putting them in an array or queue in the parent's local data. I haven't played with that option so I can't say for sure if it's opening up another world of hurt. Worth a punt maybe?

0 Kudos
Message 3 of 22
(3,377 Views)

I'm the collaborator mentioned earlier. Here is a diagram of what we are trying to do.

 

0 Kudos
Message 4 of 22
(3,370 Views)

I did not mention in the opening post that I am using a queue technique for the private class data (not the list of child class instances that you are probably referring to). That is, the private data for the parent is a reference to a queue. The queue data type is a type definition of the variables that I need. The same is true for the child class; the private data is a queue refnum to a queue with type def'd data type.

 

Even still, if I add an array of child class refnums to the parent's type def, and modify the queue refnum for the new data type, I get the compile-time errors. I have not yet tried abstracting the child class references via variant yet; this technique holds some promise.

 

I have used the variant routine in the past with great success. I'm reluctant to use it for this application because it seems like this application need should be a common one for parent/child relationship. I will surprised if a more elegant solution is not available. I also think that using a variant to break the circular referencing between my classes is a bit too abstracting.

 

I have a few thoughts that I am prototyping...

0 Kudos
Message 5 of 22
(3,367 Views)

I personally don't understand what it is you're actually trying to do, but an alternative to the variant method is to use a grandparent class (such as LabVIEW Object) instead of the child class and then downcast it at run-time. You can set the input on the VI that writes it to be of child class to ensure there are no run-time errors.

 

The reason LV doesn't allow you to put a class inside its own definition is that LV does a static allocation of values at edit time and this creates an infinite recursive loop (i.e. the class has an instance of itself which has another instance of itself and so on). This could probably be resolved with special code in LV, but it wasn't, and the workaround is easy enough.

 

If this doesn't help, maybe you can try explaining your issue with actual code and the actual terms you're using, so that we can understand better.


___________________
Try to take over the world!
0 Kudos
Message 6 of 22
(3,335 Views)

I can't tell what you're trying to do, either, but a common technique I use is to have a child that has an array of its parent (the reverse of what you are doing).  The array of parent can hold any children of parent (including the original child, making this a recursive data structure).  

0 Kudos
Message 7 of 22
(3,303 Views)

@tst wrote:

 

...but an alternative to the variant method is to use a grandparent class (such as LabVIEW Object) instead of the child class and then downcast it at run-time. You can set the input on the VI that writes it to be of child class to ensure there are no run-time errors.


Good point. That's actually better form than using a variant, IMO.

 

@The OP- do you understand what a child class means? A tree may have many leaves, but a leaf class would not be a meaningful child of tree class. The child class should be a 'more specific' version of the parent. E.g. 'fruit tree' could be a child of tree. Not implying you don't understand, just trying to clarify the problem.

 

Also, why do you have your class fields all stored as queue elements? This seems to add a lot of complication for no benefit. I would just use queues where they are useful and leave the rest as plain string, int etc.

0 Kudos
Message 8 of 22
(3,292 Views)

What I am trying to do:

I have one or more TCP connections that I am using. The parent class is the TCP connection. The private data for the class is a queue reference. The queue data type is a type def cluster of relevant parameters. The queue has a maximum of 1 element. The reason for this abstraction is that our applications use many TCP connections "simultaneously." As such, we want almost all of the TCP support VIs to be reentrant. This means that we need semaphore action when connection parameters are changed, and we use the queue to achieve this.

 

The TCP standard guarantees that each message is delivered intact, but does not guarantee message order. Sending large waveforms (or data from a continuously measuring process) requires additional work to ensure that the messages are correctly reordered on the receive end. We created an Ordered Data Stream (ODS) construct to accomplish this. That is the child class. Each TCP connection has 0 or more ODS. Each ODS inherits all the TCP settings from the parent, and can use the parent communication functions. It seems this is a textbook example of the usefulness of inheritance.

 

However, all good parents are able to keep track of their children. The TCP class needs to be able to track all active ODS instances on that TCP connection. We are struggling with the best method to use for the TCP class to keep track of all ODSs. Adding an array of ODS class instances to the TCP "private data" does not work, due to circular referencing between parent and child classes.

 

In response to trying a grandparent class:

We tried using a grandparent class. We added an array of grandparent classes, from which the TCP class inherited. The array is actually ODS instances that have been (2X) upcast from ODS to grandparent (more general class) to be stored in the TCP class data. We found that adding the array of grandparent classes to the TCP class created a VI that could not compile when we attempted to place the type def cluster ("class data") on the block diagram of a VI in the TCP class.

0 Kudos
Message 9 of 22
(3,247 Views)

Just as an aside, but TCP does guarantee message order.  It's an ordered data stream itself.

0 Kudos
Message 10 of 22
(3,242 Views)