paragui-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[paragui-users] reference-counter test


From: Andrew Ford
Subject: [paragui-users] reference-counter test
Date: Thu, 9 May 2002 10:52:02 -0700 (PDT)

Hi guys,
  This is a little test reference counter I wrote as a
"proof-of-concept" for the widget reference counter
Alex and me have been talking about.  I would
appreciate it very much if you would test it on your
compilers (particularly codewarrior, which I know some
of you are using).  It has been tested on gcc 2.96 and
vc6sp5.  The potential problem with it is the crummy
template handling in many compilers (particularly
visual C++, which is a piece of crap, frankly).  I
don't suppose anybody is using one of the borland C++
compilers are they?  Does anybody happen to have any
comments, did I screw something up?

Anyway, a list of compilers I'd like to know this
works on:

codewarrior (what versions?)
intel C++
borland C++ ( 5+ )
gcc 2.95.3 and 3.x, as well as cygwin and mingw32.
maybe other unix compilers if anybody is using them :)

thanks,

Andrew.

__________________________________________________
Do You Yahoo!?
Yahoo! Shopping - Mother's Day is May 12th!
http://shopping.yahoo.com
// File: pgref.h
// reference counted (semi)smart pointers intended for paragui use.

#ifndef _PGREF_H_
#define _PGREF_H_

typedef unsigned int Uint32;

#include <functional>

#if defined( _MSC_VER )
#define PARAGUI_ANTISOCIAL_COMPILER
#endif

template< typename T > class ref
        // Simple non-customizable reference-counted smart pointer for
        // incidentals like file lists and other non-widgets that need to be
        // cleaned up after use.
{
        public:

                ref( const ref &other )
                {
                        refObject = other.refObject;
                        refCount = other.refCount;
                        ++(*refCount);
                }

                void operator=( ref &other )
                {
                        if( refCount != NULL )
                                // We're pointing to something, so release the 
reference.
                        {
                                decRef();
                        }
                        refObject = other.refObject;
                        refCount = other.refCount;
                        ++(*refCount);
                }

                ~ref()
                {
                        if( refCount != NULL ) // We haven't been reset.
                        {
                                decRef();
                        }
                }

                T& operator*()
                {
                        return *refObject;
                }

                T* operator->()
                {
                        return refObject;
                }

                ref() // Here be dragons.  Be careful.
                {}

        #ifndef PARAGUI_ANTISOCIAL_COMPILER // Doesn't like these friends.

                // I need to know if these work in all compilers, otherwise 
we'll define the above for those compilers.
                friend ref< T > createRef< T >( T *object );
                friend void resetRef< T >( ref< T > &r );
                friend Uint32 getRefCount< T >( const ref< T > &r );
                friend T *getRealPointer< T >( const ref< T > &r );

        protected:

        #endif // PARAGUI_ANTISOCIAL_COMPILER

                void decRef()
                {
                        --(*refCount);
                        if( *refCount == 0 )
                                // No more referers, delete the object...
                        {
                                delete refCount;
                                delete refObject; // May want to use an 
allocator object for this.
                        }                       
                }

                T *refObject;
                Uint32 *refCount;
};

// The reference types shouldn't have member functions, so these are defined 
outside ref.
// Think about confusing ref.reset() with ref->reset() in the pointee, for 
instance.

template< typename T > ref< T > createRef( T *object )
{
        ref< T > temp;
        temp.refObject = object;
        temp.refCount = new Uint32;
        *(temp.refCount) = 1;
        return temp;
}

template< typename T > Uint32 getRefCount( const ref< T > &r )
{
        return *(r.refCount);
}

template< typename T > T *getRealPointer( const ref< T > &r )
{
        return r.refObject;
}

template< typename T > void resetRef( ref< T > &r )
        // Beware, after calling this r should be treated as uninitialized.
{
        r.decRef();
        r.refObject = NULL;
        r.refCount = NULL;
}


template< typename T > class lessRef :
        public std::binary_function< ref< T >, ref< T >, bool >
        // An adaptable std::less functor for your convenience.
        // I can't seem to specialize std::less< ref< T > >, thanks
        // to visual C++...
{
        bool operator()( ref< T > &lhs, ref< T > &rhs ) const
        {
                return std::less< T* >( getRealPointer( lhs ), getRealPointer( 
rhs ) );
        }
};


#endif // pgref.h
#include <iostream>
#include <vector>
#include <string>
#include "pgref.h"

typedef ref< int > intref;

using namespace std;

// Something a little more substantial to half-assedly test the instantiation.
typedef std::vector< std::string > filenameVect;
typedef ref< filenameVect > filenameVectRef;

void dummyFunc( filenameVectRef &fvr )
        // Lets instantiate some stuff!
{
        filenameVect *temp = new filenameVect;
        *temp = *getRealPointer( fvr ); // Copies the pointee.
        filenameVectRef fvr2 = createRef( temp ); // Now we can forget about 
temp, since fvr2 owns it.
        std::cerr << "How many refs? (should be 1) " << getRefCount( fvr2 ) << 
endl;
        // Hmm, I've changed my mind, I don't want this anymore...
        resetRef( fvr2 );
}

int main( int argc, char **argv )
{
#if defined( MWCW )
        std::cerr << "Hey look!  I successfully detected codewarrior!" << endl;
#endif
        intref a( createRef( new int ) );
        intref b( a );
        intref c( a );
        resetRef( c );
        intref d( b );
        // We've referenced four times, and reset once, so this should be three:
        std::cerr << "Reference Count: (should be 3) " << getRefCount( a ) << 
endl;
        std::cerr << "Here's the address of the pointee: " << getRealPointer( a 
) << endl;

        filenameVectRef fvr( createRef( new filenameVect( 10 ) ) );
        dummyFunc( fvr );

        return 0;
}

reply via email to

[Prev in Thread] Current Thread [Next in Thread]