4.2 Abstract Bases as Interfaces Approach Contd ...

RESOURCE MANAGEMENT

Lets have a look into the following code:

void f (void) {   
   IFastString *pfs = 0;   
   IPersistentObject *ppo = 0;   
   pfs = CreateFastString("Feed BOB");   

   if (pfs) { ppo = (lPersistentObject *)
             pfs->Dynamic_Cast("IPersistentObject");     
   if (!ppo)       
     pfs->Delete();     
   else {       
     ppo->Save(IC:\\autoexec.bat");       
     ppo->Delete();     
   }   
  }}


In the above example the Delete has been called for interfaces ( but all interface will have same copy Delete method and hence will not be a problem), which will in-turn deletes the fast track object. 
Just imagine so many interfaces can be pointing to the object. How to know when the Delete needs to be called.Now the client is responsible to keep track of the Interfaces that are referencing the object and delete it only when it is sure about it.This might be simple according to the above code , but considering big implementations the burden is huge and error prone.


The best way to avert this issue is by moving the responsibility to the DLL. A simple solution is to keep the a count of when the object is duplicated and and when deleted. 

class IExtensibleObject {
public:
  virtual void *Dynamic_Cast(const char* pszType) =0;
  virtual void DuplicatePointer(void) = 0;
  virtual void DestroyPointer(void) = 0;
}; 

The interface IExtensibleObject has now been updated with two new functions - DuplicatePointer and DestroyPointer.  In the DLL we need to make sure that the counter is increased when ever the object reference and creation is requested. THE ONLY shift toward client is to call the DestroyPointer when ever it is done with the Interface. 

This was DLL knows how many Interfaces are still referencing the object and delete it when it knows none are referencing it.


class FastString : public IFastString,public IPersistentObject {
int m_cPtrs; // count of outstanding ptrs
 ... ... 
public:
 ... ... 
 // initialize pointer count to zero
 FastString(const char *psz) : m_cPtrs(O) {}

 void DuplicatePointer(void) {
 // note duplication of pointer
   ++m_cPtrs;
 }
 void DestroyPointer(void) {
 // destroy object when last pointer destroyed
 if (--m_cPtrs == 0)
  delete this;
 }
 ... ...
} ;


The places where we need to increment the counter.


IFastString* CreateFastString(const char *psz) {
   IFastString *pfsResult = new FastString(psz);
   if (pfsResul t)
      pfsResult->DuplicatePointer();
   return pfsResult;
}

void *FastString::Dynamic_Cast(const char *pszType) {
void *pvResult = 0;
   if (strcmp(pszType, "IFastString") == 0)
      pvResult = static_cast<IFastString*>(this);
   else if (strcmp(pszType, "IPersistentObject") == 0)
      pvResult = static_cast<IPersistentObject*>(this);
   else if (strcmp(pszType, "IExtensibleObject") == 0)
      pvResult = static_cast<IFastString*>(this);
   else
     return 0;

  ((IExtensibleObject*)pvResult)->DuplicatePointer();

return pvResult;
}


At this stage the client implementation would be very simple and he just has to call DestroyPointer once he is done using the interface.

voi d f(voi d) {
   IFastString *pfs = 0;
   IPersistentObject *ppo 0;

   pfs = CreateFastString("Feed BOB");
 
   if (pfs) {
      ppo = (IPersistentObject *)
               pfs->Dynamic_Cast("IPersistentObject");
      if (ppo) {
         ppo->Save("C:\\autoexec.bat");
         ppo->DestroyPointer();
      }
      pfs->DestroyPointer();
  }
}








No comments:

Post a Comment