It is critical that the objects not be deleted while the stream is still holding references to them, and this is exactly the functionality that IMRefCounted provides.
Prior to streaming data, a context frame should be enabled. If your function is streaming a series of objects that contain aliases, and it is important that those aliases be preserved, either your function or some streaming function further up the call chain must establish the context frame. For example, your implementation of the writeToStream function for a collection element class does not need to create a context explicitly, because a writeObject call upon the collection class holding the element will result in a call to your writeToStream function, and a context frame will already exist. But if some other function is iterating through the collection and writing objects to a stream, outside the context of a writeObject call, then that iterating function must create a context frame for the stream data.
Consider this example:
aStream = IDataStream::createMemoryStream(); { IStreamContextFrame aContext(*aStream); aStream->writeObject(obj1); aStream->writeObject(obj2); } // The context is ended when the IStreamContextFrame object goes out // of scope. delete aStream;
An additional object that is referenced by both obj1 and obj2 will appear on the stream only once. After an object has been written to the stream once, any additional writes of the same object will be recognized as duplicates, and a tag referring to the first instance of the object will be written instead.
Note: Each top level writeObject and writeAliasedObject function automatically creates a context that lasts for the duration of that writeObject or writeAliasedObject function call. If one of the objects being streamed (obj1, for example) contains multiple references to an additional object, only one instance of that additional object will be streamed as consequence of streaming the enclosing object (obj1). In this case, you need not explicitly create a context.
To stream objects out monomorphically, create a stream and use the stream out operator (operator>>=). In the following example, the call to IDataStream::createMemoryStream() creates the data stream. The stream out operator writes primitive data to the stream. This overloaded operator also writes out the object mySimpleObject according to the implementation of mySimpleObject::writeToStream.
IDataStream* myStream = IDataStream::createMemoryStream(); myData >>= *myStream; mySimpleObject >>= *myStream;
To stream objects back in monomorphically, use the stream in operator (operator<<=):
myData <<= *myStream; mySimpleObject <<= *myStream;
The stream out function ::writeObject polymorphically writes the object aliased by objectPtr to the stream. Given an IDataStream*:
Base* objectPtr = new Derived; ::writeObject(objectPtr, *myStream);
To stream the object back in polymorphically, use the polymorphic stream in function ::readObject. Given an IDataStream&:
Base* objectPtr; ::readObject(objectPtr, myStream);
This will "resurrect" an instance of the class Derived and assign objectPtr a pointer to the derived class instance.
Introduction
to the Streaming Classes
Aliased
Objects
Monomorphic
Streaming
Polymorphic
Streaming
Data
Streams
Application
Data Interfaces
Adding Streaming Support
to Structs and Simple Classes
Creating a Streamable
Class
Instantiating a Data
Stream
Transitioning from Older
Streaming Constructs