Interface IPersistable
is a sub-interface of IObject.
Only objects that implement IPersistable
may persist (with an OID) in a
PersistStore.
The OID
is assigned when (and only when) the object first becomes reachable from a persistent object.
Note that it is common for objects to implement IPersistable
and never become persistent.
The IPersistable
interface only represents a capability to become persistent.
A class implements the IPersistable
interface in order for object instances of that class to persist on
the hard-disk with an independent identity.
The class must be reflected, and have a reflected default constructor and a reflected copy constructor.
An object that implements IPersistable
is not necessarily persistent because a
PSpace
implements persistence by reachability.
When an object implements IPersistable
, it only means that it is able to
persist - it is merely a capability. In that sense type is orthogonal to persistence.
$interface+ IPersistable : IObject
{
void VisitPrefs(IPrefVisitor& v) const;
bool RepresentsSubTree() const;
void Serialise(Archive& ar) const;
InputArchive Deserialise(InputArchive ar);
void OnCreate(bool local);
PersistObjState& GetPersistObjState() const;
};
OnCreate()
is called with local
equal to true for a bootstrapped root
when it is first created.
OnCreate()
is also called on each object within a working set when the object is
first created.
It is called with local
equal to true if the object was locally generated on that
working set, and with local
equal to false if the object was created as a result
of a received operation.
A mixin named PersistableMixin
is used to help implement this interface - for example by providing
the PersistObjState
for a persistent object.
The serialisation methods
(Serialise
and Deserialise
) must
be implemented in order to allow the object state to be converted to or from a sequence of octets.
Often the persistent objects form trees, so every object represents the root node of a subtree.
In that case RepresentsSubTree()
should be implemented as returning true.
Trees allow for simple recursive algorithms for operations such as cloning and deleting the objects, rather than more complex algorithms for arbitrary object graphs.
Objects that implement IPersistable
are expected to have a reflected default constructor in
order to support dynamic creation. More specificaly this is the m_createFn
member of the
associated ReflectedClass.
This constructor is run every time the object is loaded into memory, therefore it only relates to
in-memory creation, rather than to the original creation. In order to allow for
customisation of the latter, classes can implement OnCreate()
.
Get the OID
allocated to the given persistable object.
Returns a null OID
if the object has not been made persistent.
$function+ OID GetOid(ptr<const IPersistable> po)
// Declares that 'child' is reachable from 'parent', so 'child' should have an OID allocated and be
// added to the PSpace
//
// It is not necessary to set the PSpace in thread local storage
$function+ void DeclareReachable(ptr<const IPersistable> parent, ptr<const IPersistable> child,bool trace = true);
The persist store layer requires that the client mark persistent objects as dirty as required. This is achieved by calling the following global function
void MarkPersistentAsDirty(ptr<const IPersistable> p)
For convenience the mixin provides a MarkAsDirty()
function that calls the global function.
// It is vital that the programmer call this for each persistable object that is modified
// as part of a transaction.
//
// Failure to call this function may result in changes not being written to disk.
// Note that this function doesn't allocate OIDs to objects reachable from po.
//
// It is not necessary to set the PSpace in thread local storage
$function+ void MarkPersistentAsDirtyWithoutTrace(ptr<const IPersistable> po);
// Makes a deep copy of the given object which may or may not be persistent (i.e. have an OID)
// The copy is created synchronously and is assumed to fit entirely in memory
// returns null if any object was found which is not reflected or is has no reflected create
// function.
$function+ ptr<IPersistable> SynchronousDeepCopyPersistableObject( ptr<IPersistable> po );
When a concrete class implements IPersistable
Xcpp generates an implementation that uses
a $mixin
called PersistableMixin
to help implement the interface.
For example it adds state to record the OID
allocated to the object, if any.
For convenience this mixin provides the method MarkAsDirtyWithoutTrace()
.
$mixin PersistableMixin
{
void MarkAsDirtyWithoutTrace() const
{
if (!IsDirty())
{
MarkPersistentAsDirtyWithoutTrace($this);
}
}
...
}