Package ome.util.mem

Class Handle

  • All Implemented Interfaces:
    java.lang.Cloneable, Copiable
    Direct Known Subclasses:
    EllipseArea, RectangleArea

    public abstract class Handle
    extends java.lang.Object
    implements Copiable, java.lang.Cloneable
    Provides the basic machinery to share the same logical state across objects with different identities.

    This class calls for a distinction between object identity and object state. Made this distinction, it becomes possible to share the same state across different objects upon copy operations. When an object is updated, a new state representation is bound to that object, while the other objects can still share the previous state. This way we can have shallow copy with the semantics of deep copy. This can result in dramatically reduced memory footprint when:

    • A considerable amount of copies of a given master object are needed.
    • You can't use references to the master object, because the copied objects need to have their own identity.
    • The number of copied objects that are going to change their state after the copy operation is small compared to the total number of copies.

    For example, think of a class R that represents a rectangle in the plane with 4 integer fields x, y, w, h, and say you want to use instances of this class to describe an ROI (region of interest) selection in a given image 3D-stack composed of 100 planes — each plane would contain a rectangle selection and all those selections would make up your ROI. Let's assume that the initial selection is a discrete 3D-rectangle that spans all planes in the stack — you would have one rectangle per plane, every rectangle would have exactly the same state, say s[x=0, y=0, w=3, h=4]. Moreover, let's assume that you will have to modify slightly this initial ROI in order to get the final selection — for example by resizing/moving a couple of rectangles within the selection. Now, when you start off with the initial selection, you could decide to clone an initial master object whose state is s — this way, you can later modify one of the copies without affecting the others. However, because Java makes no distinction between object identity and state, you would have in memory 100 references and 100 copies of the same logical state s, while you actually only need one.

    The purpose of this class is to help you save memory in situations like that just described by approximating the semantics of the well known Handle/Body and Counted Body idioms often found in C++ programs. A given class abstraction is implemented by two actual classes which replicate the same class interface. One class, the Handle, takes on the role of an object identifier and forwards all calls to the other class, the Body, which implements the actual functionality. Clients can only access instances of the Handle which can all share the same Body object whenever appropriate.

    The way this works in our case is pretty easy. An Handle class extends this base Handle class and provides a reference to an instance of the corresponding Body class. The concrete Handle class exposes the same interface as its corresponding Body (this is not an absolute requirement, but usually an implementation trade-off) and has no state — in fact, the state is hold by the associated Body object. The Handle just forwards to the Body any call that only reads the Body's state. However, it must call the breakSharing protected method before forwarding any call that modifies the Body's state. It is crucial that concrete Handle classes stick to this rule. In fact, the copy method simply rebinds a new Handle to the existing Body, so subclasses must notify any incumbent change to the Body's state for the Handle to break state sharing. Lastly, it's also fundamental that the Body class implements the Copiable interface correctly for all this to work properly.

    Since:
    OME2.2
    • Constructor Summary

      Constructors 
      Modifier Constructor Description
      protected Handle​(Copiable body)
      Subclasses use this constructor to specify the Body instance this handle will be paired up with.
    • Method Summary

      All Methods Instance Methods Concrete Methods 
      Modifier and Type Method Description
      protected void breakSharing()
      Subclasses must call this method before forwarding any call that modifies the Body's state.
      java.lang.Object copy()
      Returns a deep copy of this object.
      protected java.lang.Object getBody()
      Returns a reference to the Body object that is currently paired up with this handle.
      • Methods inherited from class java.lang.Object

        clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
    • Constructor Detail

      • Handle

        protected Handle​(Copiable body)
        Subclasses use this constructor to specify the Body instance this handle will be paired up with. Subclasses must pass in a newly created object.
        Parameters:
        body - Reference to the Body object. Mustn't be null.
    • Method Detail

      • getBody

        protected java.lang.Object getBody()
        Returns a reference to the Body object that is currently paired up with this handle. The type of the returned object is the same as the one of the object that was passed to this class' protected constructor. However, the object returned by this method could be different from the one initially passed in at creation time if the breakSharing method has been invoked. For this reason, subclasses mustn't cache a reference to the object returned by this method. Moreover, subclasses must never leak out a reference to the returned Body object.
        Returns:
        The Body object.
      • breakSharing

        protected final void breakSharing()
        Subclasses must call this method before forwarding any call that modifies the Body's state.
      • copy

        public final java.lang.Object copy()
        Returns a deep copy of this object. To be precise, this method returns an object that will behave like a deep copy, but has a negligible memory footprint until an attempt to change its state is made. Then the whole original state is restored in memory so that the state change operation can take place.
        Specified by:
        copy in interface Copiable
        Returns:
        A deep copy of this object. The class of the returned object is the same as the class of this object.