Using the OdRxObjectImpl template in the example of reference counting involves implementing the TestStaticInstance() and TestDynamicInstance() functions.
To work with smart pointers, you must derive your class from the OdRxObject class when you define it and define the smart pointer type using the OdSmartPtr template:
class MyObj : public OdRxObject
{
public:
MyObj();
~MyObj();
};
typedef OdSmartPtr<MyObj> MyObjPtr;
To add the standard smart pointer implementation for a static instance of your own class, you must use the OdRxObjectImpl template when you declare the variables in the code. The test function has the following implementation:
void TestStaticInstance()
{
OdRxObjectImpl<MyObj> my;
RefCountTest(&my);
odPrintConsoleString(L"\nReturn from RefCountTest()\n Reference counter: %d\n", my.numRefs());
getch();
}
To add the standard smart pointer implementation for a dynamic instance of your own class, you must declare a smart pointer in the code and use the OdRxObjectImpl template together with the pseudo-constructor without the new operation. The test functions have the following implementation:
void TestDynamicInstance()
{
MyObjPtr pSmart0 = OdRxObjectImpl<MyObj>::createObject();
RefCountTest(pSmart0.get());
odPrintConsoleString(L"\nReturn from RefCountTest()\n Reference counter: %d\n", pSmart0->numRefs());
getch();
}
To insert the smart pointer functionality for all classes derived from your own class, you must derive your class from the OdRxObject class through the OdRxObjectImpl template when you define it and redefine the pseudo-constructor in the derived class:
class MyObj : public OdRxObjectImpl<OdRxObject>
{
public:
static OdSmartPtr<MyObj> createObject()
{
return OdSmartPtr<MyObj>(new MyObj, kOdRxObjAttach);
}
public:
MyObj();
~MyObj();
};
typedef OdSmartPtr<MyObj> MyObjPtr;
You do not need to use the OdRxObjectImpl template in the code when you declare the variables. The test function for static instances has the following implementation:
void TestStaticInstance()
{
MyObj my;
RefCountTest(&my);
odPrintConsoleString(L"\nReturn from RefCountTest()\n Reference counter: %d\n", my.numRefs());
getch();
}
The pseudo-constructor is needed for dynamic instances and is named createObject. It must create an instance of the defined class and return the smart pointer to it. This smart pointer must have the same class type. The createObject() method is defined in the base class and is not accessed in the derived class. You must define your own createObject() method and represent it in your own class. The pseudo-constructor must suppress incrementing of the reference counter because when an instance is created, its reference counter is set to one by default. The createObject() method uses the kOdRxObjAttach option when it creates the smart pointer using the OdSmartPtr template. The test function for dynamic instances has the following implementation:
void TestDynamicInstance()
{
MyObjPtr pSmart0 = MyObj::createObject()
RefCountTest(pSmart0.get());
odPrintConsoleString(L"\nReturn from RefCountTest()\n Reference counter: %d\n", pSmart0->numRefs());
getch();
}
If you do not define the pseudo-constructor in the derived class, you must create the dynamic instance using the new operator and create the first smart pointer to it using the kOdRxObjAttach option to suppress incrementing of the reference counter in the code. All subsequent smart pointers are created normally without this option. The last smart pointer destroys the instance. The test function has the following implementation:
void TestDynamicInstance()
{
MyObj* pMyObj = new MyObj;
MyObjPtr pSmart0(pMyObj, kOdRxObjAttach);
RefCountTest(pSmart0.get());
odPrintConsoleString(L"\nReturn from RefCountTest()\n Reference counter: %d\n", pSmart0->numRefs());
getch();
}
The constructor and destructor for the MyObj class have the following implementation:
MyObj::MyObj()
{
odPrintConsoleString(L"\nObject is created [counter: %d]\n", numRefs());
}
MyObj::~MyObj()
{
odPrintConsoleString(L"\nObject is destroyed\n");
}
The result of reference counting, for both the static instance and dynamic instance, are identical:
Object is created [counter: 1]
1.(pMy)->(pSmart1)
Reference counter: 2
2.(pSmart1)->(pSmart2),(pSmart3)
Reference counter: 4
3.(pSmart2)=NULL
Reference counter: 3
4.(pSmart3)->(pSmart4),(pSmart5)
Reference counter: 5
5.(pSmart1)=NULL, (pSmart4)=NULL
Reference counter: 3
6.(pSmart1)=NULL, (pSmart3)=NULL
Reference counter: 2
Return from RefCountTest()
Reference counter: 1
Object is destroyed
Return from Test
When the test function creates the instance of the MyObj class, the reference counter of the instance gets the value 1. When the function sets the address of the instance to the first smart pointer, the reference counter increments its own value 1+1=2. When the function creates the second and third smart pointers and assigns the value of the first smart pointer to them, the reference counter increments its own value by two 2+2=4. When the function assigns NULL to the second smart pointer, the reference counter decrements its own value 4-1=3. When the function creates the fourth and fifth smart pointers and assigns the value of the third smart pointer to them, the reference counter again increments its own value 3+2=5. When the function assigns NULL to the first and fourth smart pointers, the reference counter decrements its own value by two 5-2=3. When the function assigns NULL to the first and third smart pointers, the reference counter decrements its own value by one 3-1=2, because the first smart pointer is NULL and does not change the reference counter. The fifth smart pointer stores the address of the instance, but the function does not assign a value for it. When the function finishes, it destroys all smart pointers just like any automatic object. Before destroying, the destructor of the smart pointer releases the reference to the assigned object. As a result, when the fifth smart pointer is destroyed, the reference counter decrements its own value 2-1. Similarly, when the TestStaticInstance() function finishes, it automatically destroys the static instance. When the TestDynamicInstance() function finishes, it destroys the zero smart pointer, which decrements the reference counter 1-1=0. As a result, the reference counter becomes zero and this last smart pointer automatically destroys the dynamic instance. The delete operator is not required; smart pointers control the memory.
Overview of Smart Pointer Classes
Creating a Standard Implementation of the Reference Counter
Example of Counting References
Copyright © 2002 – 2020. Open Design Alliance. All rights reserved.
|