|   
      
        
        Object ownership in DynObj
        Here we will look at object ownership and destruction, object sharing and 
        tracking over DynObj plugin boundaries.
        
        
        
          Single strong point of ownership
        The default ownership model is single point strong ownership, implemented
        through the DynObj interface. An object is destroyed using the member 
        function DynObj::doDestroy():
            - 
              DynObj *pdo = /* instantiate object */;
 
              // Use object  
              pdo->doDestroy();    //  The object is destroyed 
              
        
        To hold references to 'single point ownership objects', weak references are used, 
        see below.
  
        
        Coming from COM or xpCOM, where reference counted objects is the only option,
        this is different. However, reference counting can be implemented with single 
        point ownership but the opposite is not true. So, the DynObj library 
        provides a more fundamental method.
        
        
          VObj, DynI and DynObj
        In many situations we access a 'sub-object' of a larger binary object
        through an interface. In this situation, ownership makes no sense. We
        are using an object without any ownership on it, so we should not be able
        to affect its life span in any way. The DynI interface fills this 
        role (or equivalently VObj which only states that an object 
        has a VTable).
  
        
        The DynObj interface derives from DynI and represents an
        object that can be created and destroyed. In particular, it adds functions
        for object destruction (doDestroy(),doDtor()).
  
        
        It is also possible for an interface to define its own methods for 
        object life time handling.
        
        
        By convention, any object that implements NotifierI is trackable.
        Knowing this, we can be sure that to receive a notification whenever the object 
        is destroyed. This allows a smart pointer to reset its reference.
  
        
        It is enough that we add an implementation of NotifierI as a base
        class for our object: 
        
            - 
            
// %% DYNOBJ class(VObj)  
            class GrowableSignal : public SignalI, public Notifier {  
            - 
              virtual const char* GetName( ) = 0;  
 
              // ... and the rest of the interface 
              
            };
              
        
        Then a host or another plugin can hold safe references to our type.
        
        Note: The template classes DynObjPtr<T>
        and DynWeakPtr<T> are smart DynObj pointers relying on this mechanism (see 
        doBase.hpp). The former can track objects in some different ways, while 
        the later one relies exclusively on NotifierI.
         
        
        
        For object tracking, there are two main implementations of NotifierI:
        
          - Notifier - This base class keeps all reference connection data 
            in member variables. 
          
 - GNotifier - This base class keeps reference data in external 
            tables and does not add extra weight to the derived type.
        
  
        
        The two does the same thing. If an object is likely to be referenced, it is best to use 1. If objects 
        of a type are only rarely referenced from outside, GNotifier is the 
        better choice.
        
        An example: The VFileBase interface represents a file in any type
        of storage media. Often we have trees with 1000+ files opened. But only
        very few of these are referenced from outside. So GNotifier is the 
        better choice here.
        
        
          Static global objects
        One useful technique for exposing some functionality from a plugin is to
        declare a single global instance of the type in the source file. Then, after
        making it publicly available, a plugin or host is free to use this object. 
        In this way, we side step the ownership issue completely (the users cannot
        affect the life time of a global instance in any way). 
  
        
        As an example, the interface StrConvI provides string conversion 
        between different character representations:
        
            - 
            
// %% DYNOBJ class(VObj)  
            class StrConvI : public DynI {  
            - 
                // Convert from UTF8 string to local 8 bit code page.
 
                virtual int docall ToLocal8Bit( const char* pu8_str, DynArrChar& out,  
                  - const char* pu8_end=NULL ) = 0; 
  
                // Convert from UTF8 to wchar_t string  
                virtual int docall ToWide( const char* pu8_str, DynArrWCharT& out,  
                  - const char* pu8_end=NULL ) = 0; 
  
              
            };
              
        
        Now in the implementation source file, we have: 
        
            
    
        Adding Notfier as a base class we make sure that any users of our 
        class gets notified, in the case this plugin is unloaded. 
        
        
          Reference counted objects
        Reference counted objects can be implemented via the interface RefCountI:
        
            - 
            
// %% DYNOBJ class(VObj)  
            class RefCountI {  
            - 
              virtual int docall IncRef() = 0;  
 
              virtual int docall DecRef() = 0;  
               
              // Utility functions, DecRef is a safer name than Release 
              inline int AddRef(){ return IncRef(); }  
              inline int Release(){ return DecRef(); }  
              
            };
              
        
        Then, any plugin or host can query for the RefCountI interface 
        and use it: 
        
            - 
              SomeVObj *psvo = /* get reference to object with VTable from somewhere */; 
 
              RefCountI *prci = do_cast<RefCountI*>(psvo);  
              if( prci ){
              - pcri->IncRef(); 
 
                 // Do what should be done...  
                
              
            
        In the core class hierarchy, the interface DynSharedI implements 
        RefCountI and delegates object destruction to DynObj::doDestroy().
        The class DynSharedC [in file doDynShared.hpp] provides an 
        implementation of this with atomic reference counting. It forms a useful base 
        class to reference counted objects.
        
        
  
        |