/* * @(#) memptr.h - Memory object pointer template class library header. * (c) 1998 Ivan Maidanski http://ivmai.chat.ru * Freeware class library source. All rights reserved. ** * Language: ISO/ANSI C++ * Tested with: Microsoft Visual C++ (R) v4.2, Watcom C++ 16/32 v11.0 * Last modified: 1998-08-25 13:55:00 GMT+04:00 */ // No library source file // class TPointer; // MEMPTR_REFCNT_TYPE #ifndef _MEMPTR_H_INCLUDED #define _MEMPTR_H_INCLUDED #ifndef __cplusplus #error This file is for use with C++ #endif // common macros declaration section (may be overriden) #ifndef MEMPTR_REFCNT_TYPE // type of same object references counter #define MEMPTR_REFCNT_TYPE unsigned #endif // special compiler directives #ifdef _MSC_VER #pragma warning(disable: 4284) // "bad return type for operator->()" #pragma warning(disable: 4514) // "unreferenced inline function removed" #endif // declaration section template class TPointer // memory object typed "smart" (with reference count) pointer { public: // constructors, destructor & copiers TPointer(); TPointer(const TObject &); TPointer(const TPointer &); ~TPointer(); TPointer &operator=(const TObject &); TPointer &operator=(const TPointer &); public: // object (data) access operator const TObject *() const; operator TObject *() const; TObject *operator->() const; TObject &operator*() const; public: // reference count manipulators void Delete(); MEMPTR_REFCNT_TYPE RefCount() const; public: // comparison int operator!() const; int operator==(const TPointer &) const; int operator!=(const TPointer &) const; public: // exceptions class TError {}; class TOutOfMemoryError : public TError {}; class TAccessNullRefError : public TError {}; class TNoAvailRefError : public TError {}; protected: // own class declaration class TContainer { public: TContainer(const TObject &Object) : Data(Object), RefCnt(1) {} public: TObject Data; MEMPTR_REFCNT_TYPE RefCnt; }; private: // internal data fields TContainer *PContainer; }; // template inline methods implementaion section template inline TPointer::TPointer() : PContainer(0) { } template inline TPointer::~TPointer() { Delete(); } template inline TPointer::operator const TObject *() const { return PContainer? &PContainer->Data : 0; } template inline TPointer::operator TObject *() const { return PContainer? &PContainer->Data : 0; } template inline TObject *TPointer::operator->() const { return PContainer? &PContainer->Data : 0; } template inline TObject &TPointer::operator*() const { if (!PContainer) throw TAccessNullRefError(); return PContainer->Data; } template inline MEMPTR_REFCNT_TYPE TPointer::RefCount() const { return PContainer? PContainer->RefCnt : 0; } template inline int TPointer::operator!() const { return !PContainer; } template inline int TPointer::operator== (const TPointer &Pointer) const { return PContainer==Pointer.PContainer; } template inline int TPointer::operator!= (const TPointer &Pointer) const { return PContainer!=Pointer.PContainer; } // template "out-of-line" methods implementaion section template TPointer::TPointer(const TObject &Object) : PContainer(0) { PContainer=new TContainer(Object); if (!PContainer) throw TOutOfMemoryError(); } template TPointer::TPointer(const TPointer &Pointer) : PContainer(Pointer.PContainer) { if (PContainer && ++PContainer->RefCnt<=0) { --PContainer->RefCnt; PContainer=0; throw TNoAvailRefError(); } } template TPointer &TPointer::operator=(const TObject &Object) { TContainer *PNewContainer=new TContainer(Object); if (!PNewContainer) throw TOutOfMemoryError(); TContainer *POldContainer=PContainer; PContainer=PNewContainer; if (POldContainer && !--POldContainer->RefCnt) delete POldContainer; return *this; } template TPointer &TPointer::operator= (const TPointer &Pointer) { if (PContainer!=Pointer.PContainer) { if (Pointer.PContainer && ++Pointer.PContainer->RefCnt<=0) { --Pointer.PContainer->RefCnt; throw TNoAvailRefError(); } TContainer *POldContainer=PContainer; PContainer=Pointer.PContainer; if (POldContainer && !--POldContainer->RefCnt) delete POldContainer; } return *this; } template void TPointer::Delete() { TContainer *POldContainer=PContainer; PContainer=0; if (POldContainer && !--POldContainer->RefCnt) delete POldContainer; } #endif