XML Binding Development Guide : PART III Advanced Topics : Chapter 7 Advanced Tasks : Working with the Handle/Body Classes
Working with the Handle/Body Classes
HydraExpress uses handle-body classes to simplify memory management, increase efficiency of the parser, and allow return-by-value semantics.
When working with the HydraExpress handle-body classes, there are some issues you should be aware of, particularly in the cases where code may require a deep copy. This section describes these common issues.
Working with Shallow and Deep Copies
In the handle-body idiom, all data is stored in the body, so methods that work with data affect all handles to the underlying body. In contrast, operations on the handle object itself affect only the handle.
Making a Shallow Copy
The copy constructor and assignment operator for a handle make shallow copies. A copy of a handle still refers to the original body, and methods that affect data operate on the original body.
Consider the following C++ code sample:
 
USAddress address1;
 
address1.setName("Robert Smith");
address1.setAddress("1234 Main Street");
address1.setCity("Detroit");
address1.setState("MI");
address1.setZipCode("48216");
 
USAddress address2 = address1; //1
 
address2.setName("Louise Jones");
address2.setAddress("567 Elm Court");
 
std::cout << "address1 is "
<< address1.getName() << " at "
<< address1.getAddress() << std::endl;
The code sample produces the output below:
 
address1 is Louise Jones at 567 Elm Court
Because USAddress is a handle class, line //1 makes address2 a handle to the body referenced by address1. Because address1 and address2 share a body, calls to setName and setAddress on either handle change the data for both handles.
Figure 3 illustrates the relationship between address1 and address2:
Figure 3 – Copy construction of handle-body classes
Making a Deep Copy
Sometimes it is important for the copy of a handle to be a deep copy, which instantiates a new body class for the new handle to reference, rather than having the new handle point to the same body class. HydraExpress datatype classes all define a clone() method for creating deep copies. If in the above example, line //1 was changed to:
 
USAddress address2 = address1.clone();
the output of the example code would become
 
address1 is Robert Smith at 1234 Main Street
since setting data on the address2 handle no longer changes the data in the address1 body.
Managing Circular References
As described in “Working with Shallow and Deep Copies”, the HydraExpress handle-body implementation uses a simple reference count to decide when to destroy a body. This strategy is efficient and accurate for most classes. However, this strategy fails when a body contains a handle to itself.
For example, the class declaration below shows a handle class that may contain an instance of itself as a data member:
 
class EMailMessage : public rwsf::XmlBindingHandle {
public:
 
// ...
 
void
setInResponseTo(const EMailMessage& message);
 
EMailMessage
getInResponseTo(void);
 
// ...
 
};
This declaration allows a class to contain itself, as shown in the sample below:
 
{
EMailMessage message;
message.setInResponseTo(message); //1 Error!
} //2
Line //1 copies the handle into the body, creating the object graph in Figure 4:
Figure 4 – Circular reference
Even though message goes out of scope on line //2, the body is never deleted. The destructor for message decrements the reference count on the body. However, the handle contained within the body still refers to the body, so the reference count on the body is not zero. Therefore, the destructor for message does not delete the body. Since no other handles exist, the program cannot replace the handle within the body. The result is a memory leak.
Note that this situation is a case where the data binding offers more flexibility than XML itself. Because the data binding uses the handle-body idiom, an element can logically contain a full copy of itself. An XML document cannot literally represent this structure. Each copy of the element would need to contain a full copy of the element, including a nested copy of the element. The nested copy of the element would also need to contain a copy of the element, including a nested copy. An XML document with this structure would require an infinite number of nested copies. For this reason, HydraExpress cannot serialize an element that contains itself either directly or indirectly.
An XML document typically represents self-containment by using a reference rather than a literal copy. For data structures that represent self-containment, we recommend rewriting the schema to allow a reference type as an alternative to containment.