By-reference classes | Implementation (2/2)

Classi By-reference - Implementazioni

In the previous post we saw various implementation techniques for using a class in by-reference mode. The techniques seen in the previous post (variables, FGV, DVR, and SEQ) are all mechanisms external to the class. With these approaches, the class remains by-value. The code outside the object allows the object itself to be used by-reference. Now, we are going to see two techniques which use code inside the class to turn it into an “intrinsic” by-reference class.

DVR as a private attribute of the class

We have already seen how a DVR can be used to store a by-value object. However, we can encapsulate the DVR inside the class, that is we can insert the DVR into the private data of the class itself making it an “intrinsic” by-reference class (without the use of the mechanisms seen in the first part). In detail, this requires:

  • Move the actual class attributes to a private cluster (preferably a type def). Create a DVR used to contain this cluster. The DVR becomes the only data in the class private data.
By-reference class with the private DVR – private data.
  • Make a constructor (we can call it init, create, or constructor) that initializes the DVR. The data stored in the DVR is the cluster specified in the point above.
By-reference class with the private DVR – constructor.
  • Make a destructor that disposes the DVR. Examples of names for this method might be: dispose or destructor.
By-reference class with the private DVR – destructor.

It is good practice not to expose the DVR reference, which should always be fully encapsulated in the class. The properties and methods of the class remain as we would have expected even if the class were by-value. However, internally, the class accesses its internal DVR for every operation (getters, setters and methods).

By-reference class with the private DVR – example of setter.

A class created in this way can be considered intrinsically by-reference. With this type of class, the wire related to this kind of object carries the reference to the DVR. Any fork of the wire duplicates the object but, due to the internal structure of the class, the reference to the DVR internal to the class is the only duplicated data.

The main advantage of this approach is that no external mechanism is needed to make the object by-reference simplifying the code in many cases. In addition, you have all the benefits that come with the usage of DVR (as seen in the other post):

  • Protection mechanisms in the data accesses.
  • Scalability.
  • Improved efficiency in memory management.
  • Established technology.

The analysis of the disadvantages regarding this technique deserves an in-depth discussion. Let’s look at them in detail:

  • You need the use of the constructor and destructor, which respectively creates and destroies the private DVR. This is quite normal in other languages but not in G-code. The developer must therefore be aware of it.
  • The by-reference object works even when used by-value. This sounds like an advantage but it is not always true. A by-reference class with the private DVR (if properly developed) can be used as if it were by-value. However, if the programmer does not know that he is handling a by-reference object, any fork of the wire carrying the object may result in an unexpected behavior. With an intrinsic by-reference object, any fork in the wire that carries the object doesn’t actually duplicate the “contained data.” The developer, unaware that he is using a by-reference object, might intentionally fork the wire carrying the object with the intention of getting two independent objects but this won’t happen with a by-reference object, therefore resulting in an unexpected behavior.
  • Possible deadlocks (if its methods are not implemented correctly). Since potentially every method, getter, and setter access the DVR, it is important to be careful not to call the DVR “recursively.” Within the In Place structure, it would be wise not to call other methods that access the class’s DVR. For example, suppose we have two methods of a class method1 and method2 that both access the contents of the DVR. Method1 also calls method2 within the In Place structure. In this scenario, method1 locks the DVR, calls method2 and waits for its completion. Method2, in turn, waits for method1 to unlock the DVR. The two methods wait for each other and a deadlock occurs. As a rule of thumb, to avoid this condition, it is a good idea to never carry the wire carrying the object inside the In Place structure that access the DVR so as to avoid nested accesses to the DVR.
By-reference class with the private DVR – possible source of deadlock. If the method that is in the In Place structure uses the class’s private DVR, you have a deadlock.
  • The class is by-reference but its derived classes are not. This is maybe the biggest disadvantage of this type of class. When you create a derived class from a by-reference class with private DVR, the derived class is by-value. If the derived class is not implemented in the same way as the parent class, the result is a hybrid class: partially by-reference and partially by-value.
SEQ as a private attribute of the class

We have already seen how a SEQ can be used to store a by-value object. As seen for DVR, we can encapsulate the SEQ inside the class, that is we can insert the SEQ into the private data of the class itself making it an intrinsic by-reference class (without the need for the mechanisms seen in Part 1). Similarly to what we have seen for DVR, in order to do this, we need:

  • Move the actual class attributes to a private cluster (preferably a type def). Create a SEQ used to contain this cluster. The SEQ becomes the only data in the class private data.
By-reference class with the private DVR – private data.
  • Make a constructor (we can call it init, create, or constructor) that initializes the SEQ. The data stored in the SEQ is the cluster specified in the previous point.
By-reference class with the private DVR – constructor.
  • Make a destructor that disposes the DVR. Examples of names for this method might be: dispose or destructor.
Classe by-reference con il DVR privato – destructor.

As seen in the previous paraghraph, it is good practice not to expose the SEQ reference, which should always be fully encapsulated in the class. The properties and methods of the class remain as we would have expected even if the class were by-value. However, internally, the class accesses its internal SEQ for every operation (getters, setters and methods).

Classe by-reference con il DVR privato – example of setter.

A class created in this way can be considered intrinsically by-reference. With this type of class, the wire related to this kind of object carries the reference to the SEQ. Any fork of the wire duplicates the object but, due to the internal structure of the class, the reference to the SEQ internal to the class is the only duplicated data.

Advantages and disadvantages of using SEQ as an internal class attribute are quite identical to those seen with DVR.

Conclusions

In this post divided into two parts we looked at the main techniques for obtaining by-reference classes. Specifically, in the first post we looked at external mechanisms to obtain a by-reference class. Then, in the second post we looked at mechanisms internal to the class itself to turn it into an “intrinsic” by-reference class.
In the next posts we will look at the most popular and most useful design patterns compatible with the LabVIEW environment.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top