ome.util.mem
Class Handle

java.lang.Object
  extended by ome.util.mem.Handle
All Implemented Interfaces:
Cloneable, Copiable
Direct Known Subclasses:
EllipseArea, RectangleArea

public abstract class Handle
extends Object
implements Copiable, 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:

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
Version:
2.2 (Internal version: $Revision: 1167 $ $Date: 2005/06/09 15:01:57 $)
Author:
Jean-Marie Burel      j.burel@dundee.ac.uk,
Andrea Falconi      a.falconi@dundee.ac.uk

Constructor Summary
protected Handle(Copiable body)
          Subclasses use this constructor to specify the Body instance this handle will be paired up with.
 
Method Summary
protected  void breakSharing()
          Subclasses must call this method before forwarding any call that modifies the Body's state.
 Object copy()
          Returns a deep copy of this object.
protected  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 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 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.


OmeroJava Api

Version: Beta4.2.1-r8614-Beta4.2-b41

Copyright © 2009 The University of Dundee. All Rights Reserved.