home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional Developers Kit 1992 November / Disc01 / Disc01.mdf / cppbeta / ibmcli / irefcnt.hp_ / IREFCNT.HPP
Encoding:
C/C++ Source or Header  |  1992-10-26  |  11.5 KB  |  392 lines

  1. /*==============================================================================
  2.  Module Name: irefcnt.hpp
  3.  
  4.  Description: 
  5.    Header file for generic "reference counting" classes.
  6.  
  7.  Copyright: (C) Copyright IBM Corporation 1992
  8.             All Rights Reserved
  9.             Licensed Materials = Property of IBM
  10.  
  11.  Usage:
  12.    This header should be #include-d in the header file for
  13.    classes that are reference counted (derived from IRefCounted)
  14.    or serve as references (derived from the IReference template 
  15.    class).
  16.  
  17.  Notes:
  18.  
  19.  Related Topics:
  20.  
  21.  History:
  22.    flag yymmdd who description
  23.    ---- ------ --- -----------------------------------------------------------
  24.         920826 law Initial
  25.         920916 law Remove "new T" as default on IReference<T>::IReference<T>
  26. ==============================================================================*/
  27. #if !defined( _IREFCNT_ )
  28. #define _IREFCNT_
  29.  
  30. /*------------------------------------------------------------------------------
  31.  Class Name: IReference
  32.  
  33.  Description:
  34.    Template class inherited from by classes serving as references to
  35.    some "reference counted" class.
  36.  
  37.  Usage:
  38.    This template class is derived from by classes wishing to serve
  39.    as "referernces."  Instances of such classes will serve as "smart
  40.    pointers" to instances of the referenced class.  Creation of
  41.    instances of this class will increment the use count of the
  42.    referenced object.  Destruction of the object will cause the
  43.    use count of the referenced object to be decremented.
  44.  
  45.    Typically, this class will only be referenced explicitly as a
  46.    public base class of the class that provides the additional
  47.    capability of the reference class.  For example,
  48.      :xmp.
  49.      class Foo;
  50.      class FooRef : public IReference<Foo> {
  51.      // Additional FooRef functions...
  52.      };
  53.      :exmp.
  54.  
  55.    The reference counted class provided as the template argument should be
  56.    derived from class IRefCounted.
  57.  
  58.    To construct an IReference, one must provide a pointer to an instance
  59.    of the referenced (reference counted) class.  By implication, then, all
  60.    constructors of the "real" reference class (derived from IReference<T>)
  61.    must provide such a pointer.  Otherwise, the reference class need take
  62.    on no additional responsibilities.
  63.  
  64.  Notes:
  65.    1. The semantics of such reference/referent classes perhaps have
  66.       some subtle complexities.  Care must be taken in any case where
  67.       either the reference or the referent behave in any sort of
  68.       extraordinary fashion.
  69.  
  70.    2. A class can also serve as a reference by having as a data member
  71.       and instance of class IReference<T>.
  72.  
  73.    3. All members of class IReference are public in order to permit
  74.       the usage described in Note 2.
  75.  
  76.  Related Topics:
  77.    IRefCounted
  78. ------------------------------------------------------------------------------*/
  79. template < class T > class IReference {
  80.  
  81. public:
  82.  
  83. /*------------------------------------------------------------------------------
  84.  Function Name: IReference :: IReference
  85.  
  86.  Description:
  87.    Standard constructor for template class IReference.
  88.  
  89.  Syntax:
  90.    IReference<T> tref( t );
  91.  
  92.  Parameters:
  93.    T     - (template arg) name of class being referenced
  94.    t     - pointer to instance of class T (or 0); the default
  95.            argument will be 0
  96.  
  97.  Return Values:
  98.    tref  - new reference to instance of class T pointed to by t
  99.  
  100.  Usage:
  101.    Usually, the real reference class is derived from IReference<T>.
  102.    Because of this, this constructor is most often invoked from the
  103.    constructor initializer list specified in the real reference
  104.    class's constructor(s).
  105.  
  106.  Exceptions:
  107.  
  108.  Notes:
  109.    1. This constructor does not increment the use count of the
  110.       referenced object.  The assumption is that the reference
  111.       count of this object will be adjusted as necessary outside
  112.       of the constructor.  Note that this corresponds to the default
  113.       behavior of class IRefCounted.
  114.  
  115.  Related Topics:
  116. ------------------------------------------------------------------------------*/
  117. IReference ( T *p = 0 )
  118.   : referent( p )
  119.   {
  120.   }
  121.  
  122. /*------------------------------------------------------------------------------
  123.  Function Name: IReference :: IReference
  124.  
  125.  Description:
  126.    Copy constructor for template class IReference.
  127.  
  128.  Syntax:
  129.    IReference<T> tref2( tref1 );
  130.  
  131.  Parameters:
  132.    T     - (template arg) name of class being referenced
  133.    tref1 - reference to const instance of IReference<T>; the
  134.            resulting reference will be constructed to refer to
  135.            the same object as does this argument
  136.  
  137.  Return Values:
  138.    tref2 - new reference to instance of class T referenced by tref1
  139.  
  140.  Usage:
  141.    Usually, the real reference class is derived from IReference<T>.
  142.    Because of this, this constructor is most often invoked from the
  143.    (default) copy constructor of this real reference class.  In most
  144.    cases, the default copy constructor will suffice.  If the real
  145.    reference class implements an explicit copy constructor then
  146.    that constructor should invoke this one via its initializer list.
  147.  
  148.  Exceptions:
  149.  
  150.  Notes:
  151.  
  152.  Related Topics:
  153. ------------------------------------------------------------------------------*/
  154. IReference ( const IReference<T> &source )
  155.   {
  156.   if ( source.referent )
  157.     source.referent -> addRef();
  158.   referent = source.referent;
  159.   }
  160.  
  161. /*------------------------------------------------------------------------------
  162.  Function Name: IReference :: ~IReference
  163.  
  164.  Description:
  165.    Destructor for the reference counting class.
  166.  
  167.  Notes:
  168.    1. The destructor simply decrements the use count of the referenced
  169.       object.
  170.  
  171.  Related Topics:
  172. ------------------------------------------------------------------------------*/
  173. ~IReference ( )
  174.   {
  175.   if ( referent )
  176.     referent->removeRef();
  177.   }
  178.  
  179. /*------------------------------------------------------------------------------
  180.  Function Name: IReference :: operator =
  181.  
  182.  Description:
  183.    Assignment operator for the template class IReference.
  184.  
  185.  Syntax:
  186.    tref2 = tref1;
  187.  
  188.  Parameters:
  189.    tref1 - instance of class IReference<T> whose referenced object is
  190.            now to be referenced by tref1 (*this)
  191.  
  192.  Return Values:
  193.    tref2 - reference to the object being assigned to
  194.  
  195.  Usage:
  196.    This function is provided in order to permit "reference" objects to
  197.    be assigned to while still preserving the reference count of the
  198.    referenced objects.
  199.  
  200.  Exceptions:
  201.  
  202.  Notes:
  203.    1. Care is taken to increment the source object's use count prior to
  204.       decrementing the use count of the object referenced by the
  205.       reference being assigned to.  This produces reliable behavior in
  206.       case a reference is assigned to itself.
  207.  
  208.  Related Topics:
  209. ------------------------------------------------------------------------------*/
  210. IReference<T>
  211.  &operator = ( const IReference<T> &source )
  212.   {
  213.   if ( source.referent )
  214.     source.referent -> addRef();
  215.   if ( referent )
  216.     referent -> removeRef();
  217.   referent = source.referent;
  218.   return *this;
  219.   }
  220.  
  221. /*------------------------------------------------------------------------------
  222.  Member Name: IReference :: referent
  223.  
  224.  Description:
  225.    Data member pointing to referenced object.
  226.  
  227.  Usage:
  228.    This member is utilized by the reference class to obtain access
  229.    to the referenced object.
  230.  
  231.  Notes:
  232.    1. The value of this member can be 0 (indicating there is no
  233.       referenced object).
  234.  
  235.  Related Topics:
  236. ------------------------------------------------------------------------------*/
  237. T
  238.  *referent;
  239. }; // template class IReference
  240.  
  241. /*------------------------------------------------------------------------------
  242.  Class Name: IRefCounted
  243.  
  244.  Description:
  245.    Base "reference counted" class.
  246.  
  247.  Usage:
  248.    This class is made a public base class for any class that is to be
  249.    "reference counted."  Such inheritance conveys the functional
  250.    characteristics of maintaining a count of all "references" to them
  251.    and deferring destruction until all such references are destroyed.
  252.  
  253.    Typically, use of this class is paired with corresponding use of
  254.    IReference<T> (where T is a subclass of IRefCounted).
  255.  
  256.  Notes:
  257.  
  258.  Related Topics:
  259.    IReference
  260. ------------------------------------------------------------------------------*/
  261. class IRefCounted {
  262.  
  263. public:
  264.  
  265. /*------------------------------------------------------------------------------
  266.  Function Name: IRefCounted :: addRef
  267.  
  268.  Description:
  269.    Add new reference to the reference-counted object.
  270.  
  271.  Syntax:
  272.    referent -> addRef();
  273.  
  274.  Parameters:
  275.  
  276.  Return Values:
  277.  
  278.  Usage:
  279.    This function must be invoked whenever a new reference to the
  280.    reference-counted object is created.
  281.  
  282.    Examples of such situations are the copy constructor and assignment
  283.    operator for reference classes.
  284.  
  285.  Exceptions:
  286.  
  287.  Notes:
  288.  
  289.  Related Topics:
  290.    removeRef
  291. ------------------------------------------------------------------------------*/
  292. void
  293.   addRef ( )
  294.     {
  295.     useCount++;
  296.     }
  297.  
  298. /*------------------------------------------------------------------------------
  299.  Function Name: IRefCounted :: removeRef
  300.  
  301.  Description:
  302.    Remove a reference to the reference-counted object.
  303.  
  304.  Syntax:
  305.    referent -> removeRef();
  306.  
  307.  Parameters:
  308.  
  309.  Return Values:
  310.  
  311.  Usage:
  312.    This function must be invoked whenever a reference to the
  313.    reference-counted object is destroyed.
  314.  
  315.    Examples of such situations are the destructor and assignment
  316.    operator for reference classes.
  317.  
  318.  Exceptions:
  319.  
  320.  Notes:
  321.    1. If the reference count goes to zero, then the object is
  322.       destroyed (and its storage released) via "delete this".
  323.       Thus, this function must never be invoked while references
  324.       to the object exist.  The call to this function must be the
  325.       last use of this object via the reference that is being
  326.       removed.
  327.  
  328.  Related Topics:
  329.    addRef
  330. ------------------------------------------------------------------------------*/
  331. void
  332.   removeRef ( )
  333.     {
  334.     if ( --useCount == 0 )
  335.       delete this;
  336.     }
  337.  
  338. protected:
  339.  
  340. /*------------------------------------------------------------------------------
  341.  Function Name: IRefCounted :: IRefCounted
  342.  
  343.  Description:
  344.    Base constructor for reference counted classes.
  345.  
  346.  Usage:
  347.    This constructor is invoked from within the initializer list of
  348.    all derived class constructors.
  349.  
  350.  Exceptions:
  351.  
  352.  Notes:
  353.    1. The resulting reference counted object will have an
  354.       initial use count of 1.  As a consequence, the resulting pointer
  355.       should be used to construct an instance of IReference<T> (so that
  356.       the reference count will be decremented and the object destroyed
  357.       at the appropriate time).
  358.    2. If the reference counted object is not allocated from free store
  359.       (via new) then the use count will remain 1 and the object will
  360.       be destructed in the normal fashion (i.e., when it goes out of
  361.       scope).
  362.  
  363.  Related Topics:
  364. ------------------------------------------------------------------------------*/
  365. IRefCounted ( )
  366.   : useCount( 1 )
  367.   {}
  368.  
  369. /*------------------------------------------------------------------------------
  370.  Function Name: IRefCounted :: ~IRefCounted
  371.  
  372.  Description:
  373.    Destructor for reference counted class.
  374.  
  375.  Exceptions:
  376.  
  377.  Notes:
  378.    1. This destructor is virtual.  This insures the deletion of the
  379.       object within function removeRef() invokes the proper destructor.
  380.  
  381.  Related Topics:
  382. ------------------------------------------------------------------------------*/
  383. virtual
  384.   ~IRefCounted ( )
  385.   {}
  386.  
  387. unsigned
  388.   useCount;
  389. }; // Class IRefCounted
  390.  
  391. #endif /* _IREFCNT_ */
  392.