Click Here!
home account info subscribe login search FAQ/help site map contact us


 
Brief Full
 Advanced
      Search
 Search Tips
[an error occurred while processing this directive]
Previous Table of Contents Next


3.  Fill out the declaration of the pointer class. The class as implemented in the sample code assumes its pointer to the ObjectContainer object is always valid. If you’re paranoid, feel free to add code that checks the validity of the pointer whenever referenced, and perhaps throw an exception to provide feedback during the debugging cycle. An invalid pointer could indicate a bug in the reference handling code somewhere. The following listing shows the filled-out ObjectPtr class (from memclass.hpp):
template <class t>
class ObjectPtr
{
   ObjectContainer<t>   *PointTo ;
   public:

   ObjectPtr( ObjectContainer<t> *source ) ;
   ObjectPtr( const ObjectPtr<t> &copyfrom ) ;

   ObjectPtr<t>& operator=( const ObjectPtr<t> &copyfrom ) ;

   ~ObjectPtr() ;

   // data access
   t*            operator->(){ return PointTo->_data ; }
   t&            operator* (){ return *(PointTo->_data) ; }
} ;
// end class definition
4.  Implement the inline functions. In How-To 13.2, functions that could not be inlined by the compiler were left in the header file for the sake of brevity. In this case, the two functions are broken out and put into their own header file to demonstrate the difference (and to get rid of the annoying warning messages cannot pre-compile headers ... code in header that some compilers spit out).
Generally, compilers cannot inline functions that contain loops; there are other general rules about what compilers can and can’t inline, but some are compiler dependent. Let the compiler worry about whether it can inline something or not because many things a compiler can (and will, if you tell it to) inline have a negative performance impact on your program. Rather, concentrate on making sure code you know should not be inlined (because of length, generally) is not declared inline. The following listing shows the inline functions for the ObjectContainer and ObjectPtr classes from memclass.hpp:
//--------------------------------------------------------------
//        In-line functions for ObjectContainer
//--------------------------------------------------------------

template <class t>
inline
ObjectContainer<t>::ObjectContainer( t* data, int array_size )
{
    _data = data ;
   ArraySize = array_size ;
   Refs = 0 ;
}

// these two functions are the core functionality of the code,
// and because they deal with the actual management of the data
// must be protected from other threads

template <class t>
inline
void ObjectContainer<t>::reference()
{
   // lock mutex here
    Refs++ ;
   // and release mutex
}

template <class t>
inline
void ObjectContainer<t>::dereference()
{
    // lock mutex here
    Refs-- ;

   // copy mutex to local variable

   if( Refs == 0 ) delete this ;

   // release mutex though local variable (this has been
   // destroyed, and so the mutex data member is no longer valid
}

template <class t>
inline
ObjectContainer<t>::~ObjectContainer()
{
   if( ArraySize > 1 ) delete[] _data ;
   else delete _data ;

   // now throw an exception if we still have objects referring to us...
    if( Refs ) throw logic_error( “ObjectContainer destructor called while \
referenced.”) ;
}

//--------------------------------------------------------------
//        In-line functions for ObjectPtr
//--------------------------------------------------------------

template <class t>
inline
ObjectPtr<t>::ObjectPtr( ObjectContainer<t> *source )
{
   source->reference() ;
    PointTo = source ;
}

template <class t>
inline
ObjectPtr<t>::ObjectPtr( const ObjectPtr<t> &copyfrom )
{
    copyfrom.PointTo->reference() ;
    PointTo = copyfrom.PointTo ;
}

template <class t>
inline
ObjectPtr<t>& ObjectPtr<t>::operator=( const ObjectPtr<t>
				       ⇒&copyfrom )
{
   // handle possible self-assignment
    if( this == &copyfrom ) return *this ;

    PointTo->dereference() ;

   copyfrom.PointTo->reference() ;
   PointTo = copyfrom.PointTo ;

    return *this ;
}

template <class t>
inline
ObjectPtr<t>::~ObjectPtr()
{
    PointTo->dereference() ;
}

The noteworthy items in the code are the reference() and dereference() member functions. These require mutexes when running in multithreaded programs to prevent an object from referencing the object while it is in the process of being deleted.
5.  Implement the out of line functions. Because these are template functions, they cannot be placed into a separate .cpp module; the compiler will need them to generate code for programs that use this class. The following code lists the out of line functions defined in memclass.hpp:
// copy constructor and assignment operator are not inlined,
// and for non-template implementations should be in a
// separate module if used with a compiler that supports
// pre-compiled headers

template <class t>
ObjectContainer<t>::ObjectContainer( ObjectContainer<t>
				     ⇒&copyfrom )
{
    ArraySize = copyfrom.ArraySize ;
   Refs = 0 ; // we are making a copy of the contained object
       // and therefore have no references.

   if( ArraySize > 1 )
   {
       // deal with an array
      _data = new t[ArraySize] ;

      for( int i = 0 ; i < ArraySize ; i++ )
	  _data[i] = copyfrom._data[i] ;
   }
   else
   {
       _data = new t ;
      *_data = *copyfrom._data ;
   }
}

template <class t>
ObjectContainer<t>& ObjectContainer<t>::operator=
			( ObjectContainer<t> &copyfrom )
{
    if( this == &copyfrom ) return *this ;

   if( Refs ) // error condition: cannot assign to container
	      // that isbeing referred to
       throw logic_error(“Tried to assign object container
 			⇒with Refs.”);

   // prevent copyfrom from being deleted while we’re copying it
   copyfrom.reference() ;

   if( ArraySize > 1 )
       delete[] _data ;
   else
       delete _data ;

   ArraySize = copyfrom.ArraySize ;

   if ( ArraySize > 1 )
   {
       _data = new t[ArraySize] ;

      for( int i = 0 ; i < ArraySize ; i++ )
	  _data[i] = copyfrom._data[i] ;
   }
   else
   {
       _data = new t ;
      *_data = *copyfrom._data ;
   }

   copyfrom.dereference() ;

   return *this ;

}

// end of file


Previous Table of Contents Next


Products |  Contact Us |  About Us |  Privacy  |  Ad Info  |  Home

Use of this site is subject to certain Terms & Conditions, Copyright © 1996-1999 EarthWeb Inc.
All rights reserved. Reproduction whole or in part in any form or medium without express written permision of EarthWeb is prohibited.