// ----------------------------------------------------------------------------
// FILE NAME: irefcnt.hpp
//
// DESCRIPTION:
//   Declaration of the classes:
//     IRefCounted
//     IReference
//
// COPYRIGHT:
//   IBM Open Class Library
//   Licensed Materials - Property of IBM
//
//   (C) Copyright IBM Corporation 1992, 1997  All Rights Reserved.
//
// Revision: 67  1.4.1.4  source/core/base/irefcnt.hpp, appsupport, ioc.v400, 980918  
// ----------------------------------------------------------------------------

#ifndef _IREFCNT_
#define _IREFCNT_

#include <ibase.hpp>
#include <iexcept.hpp>

#if ( IC_OBSOLETE <= IC_OBSOLETE_3 )

#if __IBMCPP__ >= 400
#pragma namemangling(compat)
#endif

#pragma pack(push,4)
#pragma enum(4)

class IC_EXPORTB IRefCounted
{
public:
    // --------------------------- Reference Counting -------------------------
    virtual void addRef();
    virtual void removeRef();

    unsigned useCount() const
    {
        return this->refCount;
    }

    static void throwNullIReference();

protected:
    // ------------------------------ Constructors ----------------------------
    IRefCounted();
    virtual ~IRefCounted();

private:
    // --------------------------------- Private ------------------------------
    unsigned refCount;
};

template < class T > class IC_EXPORTB IReference
{
public:
    // ------------------------------ Constructors ----------------------------
    IReference ( T* p = 0 ) :
        referent( p )
    {
    }

    IReference(const IReference<T>& source) :
        referent(source.referent)
    {
        if (source.referent)
            source.referent->addRef();
    }

    ~IReference ( )
    {
        if (referent)
            referent->removeRef();
    }

    IReference<T>& operator=(const IReference<T>& source)
    {
        if (source.referent)
            source.referent->addRef();

        if (referent)
            referent->removeRef();
        referent = source.referent;
        return *this;
    }

    IReference<T>& operator=(T* p)
    {
        if (p)
            p->addRef();
        if (referent)
            referent->removeRef();
        referent = p;
        return *this;
    }

    // -------------------------------- Operators -----------------------------
    T* operator->()const
    {
        if ( !referent )
            IRefCounted::throwNullIReference();
        return referent;
    }

    T& operator*() const
    {
        if (!referent)
            IRefCounted::throwNullIReference();
        return *referent;
    }

    operator T*() const
    {
        return (referent);
    }

private:
    // --------------------------------- Private ------------------------------
    T* referent;

};

#pragma enum(pop)
#pragma pack(pop)

#if __IBMCPP__ >= 400
#pragma namemangling()
#endif

#endif // ( IC_OBSOLETE <= IC_OBSOLETE_3 )

#endif // _IREFCNT_
