home *** CD-ROM | disk | FTP | other *** search
Text File | 1998-06-12 | 7.3 KB | 332 lines | [TEXT/CWIE] |
- /*
- File: Object.cp
-
- Contains: Support for Reference Counted Objects
- Written by: Steve Sisak
- Copyright: © 1996-98 by Steve Sisak, all rights reserved.
- */
-
- #ifndef __OBJECT__
- #include "Object.h"
- #endif
- #ifndef __EXCEPTIONS__
- #include "Exceptions.h"
- #endif
- #ifndef __DEBUGWRITE__
- #include "DebugWrite.h"
- #endif
- #ifndef __THREADS__
- #include <Threads.h>
- #endif
-
- typedef struct type_info_struct type_info_struct; // forward
-
- typedef struct type_info_base_list { // type info base list
- type_info_struct *baseti; // pointer to bases type_info struct (0: end of list)
- long offset; // offset of base in main class (0x80000000 : ambiguous/no access list follows
- } type_info_base_list;
-
- typedef struct type_info_ambighead { // type ambiguous/no access base list header
- void *baseti; // pointer to bases type_info struct (0: end of list)
- long offset; // offset of base in main class (|=0x80000000)
- long bases; // number of type_info_base_list elements (public bases)
- } type_info_ambighead;
-
- struct type_info_struct { // type info data structure
- char *tname; // pointer to type name
- type_info_base_list *baselist; // pointer to base list
- };
-
- typedef struct RTTIVTableHeader { // RTTI header in a vtable
- type_info_struct *type_info_ptr; // pointer to complete class type_info struct
- long complete_offset;// offset of complete class
- } RTTIVTableHeader;
-
-
- //==============================================================================
-
- #pragma segment Main
-
- DefineClassNoBaseAbstract(TObject);
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- #if qDebug
- TObject::~TObject()
- {
- if (fReferenceCount != 0)
- {
- DebugWrite("\p~Object() - deleting ");
- WriteToDebugger(false);
- DebugWrite("\p with ");
- DebugWriteNum(fReferenceCount);
- DebugWriteLn("\p active reference(s)", qDebug);
- }
- }
- #endif
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- void TObject::Initialize()
- {
- #if qObjectInspector || qDebug
- void* base = dynamic_cast<void*>(this);
- #endif
-
- #if qDebug
- RTTIVTableHeader* vtable = *(RTTIVTableHeader**) &(&fClassOffset)[1];
-
- fBaseAddress = base;
- fClassName = vtable->type_info_ptr->tname;
-
- unsigned long freeStack;
-
- OSErr err = ThreadCurrentStackSpace(kCurrentThreadID, &freeStack);
-
- if (err != noErr || freeStack < 10000)
- {
- DebugWriteLn("\pPossible infinite recursion (<10k stack left)", true);
- }
- #endif
-
- #if qObjectInspector
- if (!IsInitialized()) // ClassID not set up yet
- {
- const ClassDesc* desc = GetClassDescDynamic();
-
- if (desc != nil)
- {
- desc->RegisterObject(*this, base);
- }
- }
- #endif
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- void TObject::Finalize()
- {
- #if qDebug
- if (fReferenceCount != 1)
- {
- // We keep duplicate warning code here as there is more valuable info
- // for the programmer on the stack than in ~TObject()
-
- DebugWrite("\pTObject::Finalize() - finalizing ");
- WriteToDebugger(false);
-
- if (fReferenceCount == 0)
- {
- DebugWriteLn("\p never initilaized", qDebug);
- }
- else
- {
- DebugWrite("\p with ");
- DebugWriteNum(fReferenceCount);
- DebugWriteLn("\p active reference(s)", qDebug);
- }
- }
- #endif
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- void TObject::Delete()
- {
- FinalizeObject(this);
-
- delete this;
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- TObject* TObject::DeepClone() const
- {
- return nil;
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- #if qDebug
- const char* TObject::GetClassName() const
- {
- return fClassName;
- }
-
- const void* TObject::GetBaseAddress() const
- {
- return fBaseAddress;
- }
-
- void TObject::WriteToDebugger(bool flush) const
- {
- const char* name = GetClassName();
- const void* base = GetBaseAddress();
-
- DebugWriteTypeAtAddress(name, base, flush ? kDebugWriteFlush : kDebugWrite);
- }
- #endif
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- void TObject::NilObjectReference()
- {
- #if qDebug
- SysBreakFunc("\pNilObjectReference\n");
- Debugger();
- #endif
-
- Throw(ePointerNil);
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- void TObject::InitializeObject(const TObject* obj)
- {
- if (obj)
- {
- if (obj->fReferenceCount == 0)
- {
- const_cast<TObject*>(obj)->Initialize();
- const_cast<TObject*>(obj)->fReferenceCount = 1;
- }
- }
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- void TObject::FinalizeObject(const TObject* obj)
- {
- if (obj)
- {
- const_cast<TObject*>(obj)->Finalize();
- const_cast<TObject*>(obj)->fReferenceCount = 0;
- }
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- void TObject::DeleteObject(const TObject* obj)
- {
- if (obj)
- {
- const_cast<TObject*>(obj)->Delete();
- }
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- TObject* TObject::NewObjectRef(const TObject* obj)
- {
- if (obj)
- {
- obj->NewReference();
- }
-
- return const_cast<TObject*>(obj);
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- TObject& TObject::NewObjectRef(const TObject& obj)
- {
- if (&obj == nil)
- {
- #if qDebug
- Debugger();
- #endif
- NilObjectReference();
- }
-
- return *NewObjectRef(&obj);
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- TObject* TObject::DeleteObjectRef(const TObject* obj)
- {
- if (obj)
- {
- const_cast<TObject*>(obj)->DeleteReference();
- }
-
- return nil;
- }
-
- //------------------------------------------------------------------------------
- // TObject::SwapObjectReference - this routine increments the reference count
- // of one object and decrements the reference count of another atomically.
- //------------------------------------------------------------------------------
-
- #pragma segment Main
- TObject* TObject::SwapObjectRef(const TObject* dec, const TObject* inc)
- {
- if (dec != inc) // cheap optimization
- {
- if (inc) // increment new object count first in
- { // case we're indirectly referencing
- inc->NewReference(); // the same object
- }
-
- if (dec) // now decrement the count of the dec
- { // object, if we fail, we also need to
- try // kill the reference we created to
- { // the new object
- dec->DeleteReference();
- }
- catch(...)
- {
- DeleteObjectRef(inc);
- }
- }
- }
-
- return const_cast<TObject*>(inc);
- }
-
-
- #pragma segment Main
- TObject& TObject::SwapObjectRef(const TObject& dec, const TObject& inc)
- {
- if (&inc == nil || &dec == nil) // this would be bad
- {
- NilObjectReference();
- }
-
- return *SwapObjectRef(&inc, &dec);
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- ObjectInitializer::ObjectInitializer(const TObject& obj)
- : fObject(obj)
- {
- TObject::InitializeObject(&obj);
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
- ObjectInitializer::~ObjectInitializer()
- {
- TObject::FinalizeObject(&fObject);
- }
-
- //------------------------------------------------------------------------------
- #pragma segment Main
-
-