When POET gets an object from the database it resolves all pointer references to other objects by loading the objects into memory and setting the pointers to the RAM address of the newly loaded object. This is usually what you want - if you have pointers in your classes you just might decide to use them, and you might encounter a few surprises if the object is not in memory.
In some cases you may not want this. There may not be enough RAM to load the objects, especially if every object is somehow connected to every other object. Or you may know that you will use some references infrequently and you want to speed up your reads by loading only those objects that are strictly necessary. This is what ondemands are for. When you create an ondemand you control when the reference is loaded into memory.
An ondemand is simply a container that holds a pointer to an object. Only persistent classes may be placed in an ondemand - POET needs the object identity to manage the reference.
PtOnDemand can also be used in sets. Sometimes sets contain objects which are too large too keep them all in memory. In this case you can define a set of ondemand members which are loaded into memory on demand.
An ondemand member is defined in your .hcd file using the ondemand keyword. Ondemands are semantically very similar to pointers. Consider the following declaration:
Child is an ondemand reference to a person. Spouse is a pointer to a person. Each of these declarations creates a reference to a person; however, Child is not automatically loaded into memory. To load the child into memory you call the child's Get() method, which provides the pointer to the newly loaded object.
For instance, if the above declaration is in the file child.hcd then PTXX will generate a file called child.hxx which contains the code needed to use Child as an ondemand reference. If you include this file in your application then you can set references using Child's SetReference() method or load a child on demand using Child's Get() method:
When you set a reference in an ondemand, you must specify whether the ondemand should take responsibility for the referenced object. If the ondemand has responsibility, it increments the link count of the referenced object and sets an internal flag. When the reference is changed or the ondemand 's destructor is called, the ondemand checks to see if it has responsibility - if so, it performs a Forget() on the referenced object. The chapter "Persistent objects" in the Programmer's Guide contains a detailed discussion of responsibility and link counts.
An ondemand may contain references to objects which reside in a different database than the object which contains the ondemand. This is discussed in detail in the chapter "Cross-database references" in your Programmer's Guide.
Files to include | Class declaration | Base class |
poet.hxx | ptondema.hxx | PtCallback |
constructor | PtOnDemand(); |
destructor | virtual ~PtOnDemand(); |
BeResponsible | void BeResponsible(); |
CheckIn | virtual int CheckIn(PtDepthMode depth = PtDEEP); |
CheckOut | virtual int CheckOut(PtWorkspace* pws, PtDepthMode depth = PtNO_ONDEMAND, PtLockMode = PtLK_WRITEvWRITE); |
Delete | virtual int Delete(PtDepthMode = PtSHALLOW); |
Forget | void Forget(); |
Get | inline int Get(PtObject*& , PtLockSpec* plk = 0, PtWatchSpec* pwatch = 0, PtBool useWS = PtTRUE); |
GetBase | inline PtBase* GetBase() const; |
GetClassId | virtual PtClassId& GetClassId(); |
GetCurrentDescId | virtual PtClassId& GetCurrentDescId(); |
GetDatabaseName | PtString GetDatabaseName() const; |
GetDescClass | virtual PtMetaType* GetDescClass(); |
GetDescId | virtual PtClassId& GetDescId(); |
GetMetaType | virtual PtMetaOnDemand* GetMetaType(); |
GetObjectInfo | virtual int GetObjectInfo(PtObjectStat& ) const; |
GetRef | PtRef& GetRef() const; |
GetServerName | PtString GetServerName() const; |
GetSurr | inline PtObjId& GetSurr(); |
IsAssigned | inline PtBool IsAssigned() const; |
IsForeign | inline int IsForeign() const; |
IsInMemory | unsigned PtBool IsInMemory(); |
IsReferenced | inline PtBool IsReferenced() const; |
Lock | int Lock(PtLockSpec* pSpec = 0); |
Make | static PtOnDemand* Make(PtBase* , const PtString& PtOnDemand); |
SetReference | inline void SetReference(PtObject*, int do_remember = 1); |
Unget | int Unget(PtObject* , PtLockSpec* plk = 0, PtWatchSpec* pwatch = 0); |
Unlock | int Unlock(PtLockSpec* pSpec = 0); |
UnsetWatch | int UnsetWatch(PtWatchSpec* pSpec = 0); |
UpdateSource | virtual int UpdateSource(PtDepthMode dmode = PtDEEP, PtLockMode lkmode = PtLK_DELETEvWRITE); |
Watch | int Watch(PtWatchSpec* pSpec = 0); |
operator = | PtOnDemand& operator = (const PtOnDemand& ondem); |
operator == | PtBooloperator == (const PtOnDemand& ondem) const; |
operator != | int operator != (const PtOnDemand& ondem) const; |
- PtOnDemand::PtOnDemand()
- PtOnDemand::PtOnDemand(PtBase* pb)
- PtOnDemand::PtOnDemand(PtOnDemand& ondem)
- PtOnDemand::PtOnDemand(PtRef& ref, PtBase* )
PtOnDemand::PtOnDemand(PtObject* pobj, int do_remember=1)
Each of these is documented separately below.
- PtOnDemand::PtOnDemand()
Empty constructor. Initializes the ondemand reference to null.
- PtOnDemand::PtOnDemand(PtBase* pb)
Constructor. Assigns the ondemand to the database.
- PtOnDemand::PtOnDemand(PtOnDemand& ondem)
Copy constructor. Creates a new ondemand, and assigns it to refer to the same object as the ondemand in the parameter list. If the original ondemand was responsible for the referenced object, this ondemand also takes responsibilty; if not, this ondemand does not take responsibility.
- PtOnDemand::PtOnDemand(PtRef& ref, PtBase* )
Constructor. A PtRef and a database are sufficient to construct a valid ondemand reference.
PtRef& ref | The new ondemand reference is set to point to the same object as this PtRef |
PtBase* | The new ondemand is assigned to this database |
- PtOnDemand::PtOnDemand(PtObject* pobj, int do_remember=1)
Constructor. If the object is assigned, sets the ondemand to point to this object.
PtObject * pobj | The object that the ondemand should point to. This object should be assigned to a database. |
int do_remember=1 | If do_remember is set to 1, the ondemand takes responsibility for the object. If it is set to 0, the ondemand does not take responsibility. |
- virtual PtOnDemand::~PtOnDemand()
- virtual int PtOnDemand::CheckIn(PtDepthMode depth = PtNO_ONDEMAND)
Calls PtObject:: CheckIn() for the referenced object, checking it into the workspace.
The depthMode determines whether referenced objects are also affected. The depth mode may be any of the following:
PtNO_ONDEMAND | The object and all referenced objects that are not ondemands are checked in |
PtDEEP | The object and all referenced objects are checked in |
0 | Success |
ERR_PT_ILLEGAL_PARAMETER | Only PtDEEP or PtNO_ONDEMAND depth modes are allowed, because PtObject*'s would be foreign after moving flat or shallow. |
- virtual int PtOnDemand::CheckOut(PtWorkspace *pws, PtDepthMode depth = PtNO_ONDEMAND, PtLockMode = PtLK_DELETEvWRITE)
Calls PtObject:: CheckOut() for the referenced object, checking it into the workspace.
PtWorkspace* pws | The workspace to check the object into |
PtDepthMode depth = PtNO_ONDEMAND | The depth mode for the checkout |
PtLockMode = PtLK_DELETEvWRITE | The lock mode for the persistent lock which the checkout leaves in the original database |
0 | Success |
ERR_PT_ILLEGAL_PARAMETER | Only PtDEEP or PtNO_ONDEMAND depth modes are allowed, because PtObject*'s would be foreign after moving flat or shallow. This error is also returned if the workspace is the same as the object's current database. |
ERR_PT_CHECKOUT_NOT_RUNNING | Could not check out because you have not called PtWorkSpace:: BeginCheckOut(). |
- virtual int PtOnDemand::Delete(PtDepthMode = PtSHALLOW)
Deletes the referenced object and clears the ondemand reference.
PtDepthMode = PtSHALLOW | Depth mode for the delete. |
0 | Success |
ERR_PT_NO_REFERENCE | The ondemand does not have a reference to an object. |
ERR_PT_NOT_ASSIGNED | The ondemand is not assigned |
If the object has not been stored or has already been deleted, Delete() returns a zero.
- void PtOnDemand::Forget()
If the ondemand is responsible for the referenced object, decrements the link count for the referenced object and removes responsibility for the object.
- inline int PtOnDemand::Get(PtObject*& , PtLockSpec* plk = 0, PtWatchSpec* pwatch = 0, PtBool useWS = PtTRUE)
Loads the referenced object into memory. When you are done with the object call Unget() to release the resources associated with it.
PtObject*& pObject | Pointer to the object. If Get() succeeds, this pointer is set to the RAM address of the referenced object. |
PtLockSpec* plk = 0 | Lock specification. If Get() succeeds, this lock is set for the referenced object. If zero, the default lock is used if there is one. |
PtWatchSpec* pwatch = 0 | Watch specification. If Get() succeeds, this watch is set for the referenced object. If zero, the default watch is used if there is one. |
bool useWS = PtTRUE | This mysterious parameter is used by POET internally, and is not present in the PTXX-generated type safe Get() functions. Just use the default. |
0 | Success. |
ERR_PT_NO_REFERENCE | The ondemand does not have a reference to an object. |
ERR_PT_OBJECT_LOCKED | The object is locked and could not be read. |
- inline PtBase* PtOnDemand::GetBase() const
Returns a pointer to the PtBase to which this ondemand is assigned.
- virtual PtClassId& PtOnDemand::GetClassId()
Returns the PtClassId which describes the ondemand. Most ondemand classes are generated by PTXX and can be used only for objects belonging to one class. Each ondemand type is registered in the class dictionary. For instance, if you have an ondemand declared like this:
GetClassId() will return the PtClassId for odBicycle.
- virtual PtClassId& PtOnDemand::GetCurrentDescId()
Returns the PtClassId which describes the object which the ondemand currently references. For instance, suppose you have an ondemand declared like this:
This ondemand can reference any kind of bicycle. If the ondemand currently references a MountainBike, GetCurrentDescId() will return the PtClassId for MountainBike, not for Bicycle.
- PtString PtOnDemand::GetDatabaseName() const
Returns the logical name of the database to which referenced object of the ondemand is assigned.
- virtual PtClassId& PtOnDemand::GetDescId()
Returns the PtClassId for the class whose objects this ondemand can contain - not the full inherited type of the object which the ondemand currently references. For instance, suppose you have an ondemand declared like this:
This ondemand can reference any kind of bicycle. If the ondemand currently references a MountainBike, GetCurrentDescId() will return the PtClassId for Bicycle, not for MountainBike.
- virtual PtMetaOnDemand* PtOnDemand::GetMetaType()
Returns the class dictionary entry which describes this particular ondemand.
- virtual int PtOnDemand::GetObjectInfo(PtObjectState& ) const
This function fills the PtObjectState with information on the requested object. The type of information depends on the full type of the PtObjectState. For instance, if you specify a PtObjStateMaxLock, you will receive information on the maximum lock for this object. PtObjStateLockList reports all locks. PtObjStateWatchList reports all active watches for each watched object, and pos iterates through only the watched objects. If you specify a PtObjStateObjectInfo, you will receive all available status information on the object.
- PtRef& PtOnDemand::GetRef() const
PtRef& PtOnDemand::GetRef(PtRef& val)
Each of these is described separately below.
- PtRef& PtOnDemand::GetRef()
Returns the PtRef for the referenced object.
- PtRef& PtOnDemand::GetRef(PtRef& val)
Sets val to the PtRef for the referenced object. Returns the new value of val.
- PtString PtOnDemand::GetServerName() const
Returns the name of the server for the database where the referenced object resides. This is useful when the object may be in a foreign database.
- inline PtObjId& PtOnDemand::GetSurr()
Returns the PtObjId for the referenced object.
- inline PtBool PtOnDemand::IsAssigned() const
Returns a non-zero value if the ondemand is assigned.
- inline int PtOnDemand::IsForeign() const
Returns a non-zero value if the referenced object resides in a foreign database.
- unsigned PtBool PtOnDemand::IsInMemory()
Returns a non-zero value if the referenced object is in memory.
- inline PtBool PtOnDemand::IsReferenced() const
Returns a non-zero value if the PtOnDemand contains a valid reference to an object.
- int PtOnDemand::Lock(PtLockSpec* pSpec = 0)
Locks the referenced object using the mode and depth from the PtLockSpec. If pSpec is zero, uses the default lock specification. If the object has not been stored or has been deleted, returns 0, but the object is not locked.
0 | Success. |
ERR_PT_NO_REFERENCE | The ondemand does not contain a valid reference. |
ERR_PT_FOREIGN_REFERENCES | The lock could not be performed because it involves objects in foreign databases. |
ERR_PT_OBJECT_LOCKED | The lock could not be performed because someone else has locked the object. |
- static PtOnDemand* PtOnDemand::Make(PtBase* , const PtString& PtOnDemand)
Creates an ondemand for a particular class and assigns it to the database. Because this function is static, you can call it globally.
PtBase* | The database to which the ondemand should be assigned |
const PtString& PtOnDemand | The name of the class which the ondemand can reference. If type safety is enabled, an attempt to set a reference to an object not belonging to this class will fail. |
0 | Failure |
PtOnDemand* | Pointer to the new PtOnDemand. |
- int PtOnDemand::SetReference(PtObject* , int do_remember = 1)
Sets the reference for an ondemand object.
PtObject * | The object to which the ondemand should refer. SetReference() will fail if this object has not been assigned to a database. If run time type checking is set on, SetReference() will fail if the object does not belong to the class that the ondemand references. |
int do_remember=1 | If do_remember is set to 1, the ondemand takes responsibility for the object. If it is set to 0, the ondemand does not take responsibility. |
- int PtOnDemand::Unget(PtObject* , PtLockSpec* plk = 0, PtWatchSpec* pwatch = 0)
Releases the resources allocated to an object using Get(). Decrements the link count and removes from memory if the resulting link count is zero.
PtObject* | Pointer to the object which was previously read using PtOnDemand::Get()PtOnDemand:: Get() |
PtLockSpec* plk = 0 | The LockSpec which was used in PtOnDemand:: Get(). If no LockSpec was used, use zero. |
PtWatchSpec* pwatch = 0 | The WatchSpec which was used in PtOnDemand:: Get(). If no WatchSpec was used, use zero. |
>=0 | The link count of the object after the Unget(). If zero, the object has been removed from RAM. |
ERR_PT_NO_REFERENCE | The ondemand does not contain a valid reference. |
ERR_PT_NOT_LOCKED | The object was not locked with the depth mode and lock mode specified in the PtLockSpec. |
int PtOnDemand::Unlock(PtLockSpec* pSpec = 0)
Removes a lock which was previously set using PtOnDemand:: Lock().
0 | Success. |
ERR_PT_NO_REFERENCE | The ondemand does not contain a valid reference. |
ERR_PT_NOT_LOCKED | The object was not locked, or it is not in the database (i.e. it was never stored or has been deleted). |
- int PtOnDemand::UnsetWatch(PtWatchSpec* pSpec = 0)
Removes a watch which was previously set using PtOnDemand:: Watch().
0 | Success. |
ERR_PT_NO_REFERENCE | The ondemand does not contain a valid reference. |
ERR_PT_NOT_WATCHED | The object was not in the database (i.e. it was never stored or has been deleted). |
- int PtObjectSet::UpdateSource(PtDepthMode dmode = PtDEEP, PtLockMode lkmode = PtLK_DELETEvWRITE)
Partially check-in the object. The checked out object is left in the workspace. The object in the original database will re-locked with 'lkmode'.
PtDepthMode dmode=PtDEEP | which subobjects belongs to this operation |
PtLockMode lkmode=PtLK_DELETEvWRITE | how the objects in the original base should be locked |
- int PtOnDemand::Watch(PtWatchSpec* pSpec = 0);
Sets a watch on the referenced object.
0 | Success. |
ERR_PT_NO_REFERENCE | The ondemand does not contain a valid reference. |
ERR_PT_FOREIGN_REFERENCES | The watch could not be performed because it involves objects in foreign databases. |
- PtOnDemand& PtOnDemand::operator = (const PtOnDemand& ondem)
- PtOnDemand& PtOnDemand::operator = (PtObject* pobj)
Each of these is described separately below.
- PtOnDemand& PtOnDemand::operator = (const PtOnDemand& ondem)
Assignment operator. Sets the ondemand to refer to the same object as the parameter. Takes responsibility if the original ondemand had responsibility.
- PtOnDemand& PtOnDemand::operator = (PtObject* pobj)
Assignment operator. Sets the ondemand to refer to the same object as the parameter. Always takes responsibility for the object. Returns a reference to the new ondemand.
- PtBool PtOnDemand::operator == (const PtOnDemand& ondem) const
- PtBool
PtOnDemand::operator == (const PtObject* pobj) const
Each of these is described separately below.
- PtBool PtOnDemand::operator == (const PtOnDemand& ondem) const
Returns a non-zero value if the two ondemands refer to the same object.
- PtBool PtOnDemand::operator == (const PtObject* pobj) const
Returns a non-zero value if the ondemand refers to the same object as the PtObject pointer.
- int PtOnDemand::operator != (const PtOnDemand& ondem) const
int PtOnDemand::operator != (const PtObject* pobj) const
Each of these is described separately below.
- int PtOnDemand::operator != (const PtOnDemand& ondem) const
Returns a non-zero value if the two ondemands do not refer to the same object.
- int PtOnDemand::operator != (const PtObject* pobj) const
Refers a non-zero value if the ondemand does not refer to the same object as the PtObject pointer.
Copyright (c) 1996 POET Software, Inc. All rights reserved. Reproduction in whole or in part in any form or medium without the express permission of POET Software, Inc. is prohibited.