/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ #ifndef _MDB_ # include "mdb.h" #endif #ifndef _MORK_ # include "mork.h" #endif #ifndef _MORKENV_ # include "morkEnv.h" #endif #ifndef _MORKFACTORY_ # include "morkFactory.h" #endif #ifndef _MORKPOOL_ # include "morkPool.h" #endif #ifndef _MORKHANDLE_ # include "morkHandle.h" #endif // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` // { ===== begin morkNode interface ===== /*public virtual*/ void morkHandle::CloseMorkNode( morkEnv* ev) // CloseHandle() only if open { if (this->IsOpenNode()) { this->MarkClosing(); this->CloseHandle(ev); this->MarkShut(); } } /*public virtual*/ morkHandle::~morkHandle() // assert CloseHandle() executed earlier { MORK_ASSERT(mHandle_Env == 0); MORK_ASSERT(mHandle_Face == 0); MORK_ASSERT(mHandle_Object == 0); MORK_ASSERT(mHandle_Magic == 0); MORK_ASSERT(mHandle_Tag == morkHandle_kTag); // should still have correct tag } /*public non-poly*/ morkHandle::morkHandle( morkEnv* ev, // note morkUsage is always morkUsage_kPool morkHandleFace* ioFace, // must not be nil, cookie for this handle morkObject* ioObject, // must not be nil, the object for this handle mork_magic inMagic) // magic sig to denote specific subclass : morkNode(ev, morkUsage::kPool, (nsIMdbHeap*)0L), mHandle_Tag(0), mHandle_Env(ev), mHandle_Face(ioFace), mHandle_Object(0), mHandle_Magic(0) { if (ioFace && ioObject) { if (ev->Good()) { mHandle_Tag = morkHandle_kTag; morkObject::SlotStrongObject(ioObject, ev, &mHandle_Object); morkHandle::SlotWeakHandle(this, ev, &ioObject->mObject_Handle); if (ev->Good()) { mHandle_Magic = inMagic; mNode_Derived = morkDerived_kHandle; } } else ev->CantMakeWhenBadError(); } else ev->NilPointerError(); } /*public non-poly*/ void morkHandle::CloseHandle( morkEnv* ev) // called by CloseMorkNode(); { if (this->IsNode()) { morkObject* obj = mHandle_Object; mork_bool objDidRefSelf = (obj && obj->mObject_Handle == this); if (objDidRefSelf) obj->mObject_Handle = 0; // drop the reference morkObject::SlotStrongObject((morkObject*)0, ev, &mHandle_Object); mHandle_Magic = 0; // note mHandle_Tag MUST stay morkHandle_kTag for morkNode::ZapOld() this->MarkShut(); if (objDidRefSelf) this->CutWeakRef(ev); // do last, because it might self destroy } else this->NonNodeError(ev); } // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` void morkHandle::NilFactoryError(morkEnv* ev) const { ev->NewError("nil mHandle_Factory"); } void morkHandle::NilHandleObjectError(morkEnv* ev) const { ev->NewError("nil mHandle_Object"); } void morkHandle::NonNodeObjectError(morkEnv* ev) const { ev->NewError("non-node mHandle_Object"); } void morkHandle::NonOpenObjectError(morkEnv* ev) const { ev->NewError("non-open mHandle_Object"); } void morkHandle::NewBadMagicHandleError(morkEnv* ev, mork_magic inMagic) const { MORK_USED_1(inMagic); ev->NewError("wrong mHandle_Magic"); } void morkHandle::NewDownHandleError(morkEnv* ev) const { if (this->IsHandle()) { if (this->GoodHandleTag()) { if (this->IsOpenNode()) ev->NewError("unknown down morkHandle error"); else this->NonOpenNodeError(ev); } else ev->NewError("wrong morkHandle tag"); } else ev->NewError("non morkHandle"); } morkObject* morkHandle::GetGoodHandleObject(morkEnv* ev, mork_bool inMutable, mork_magic inMagicType, mork_bool inClosedOkay) const { morkObject* outObject = 0; if (this->IsHandle() && this->GoodHandleTag() && (inClosedOkay || this->IsOpenNode())) { if (!inMagicType || mHandle_Magic == inMagicType) { morkObject* obj = this->mHandle_Object; if (obj) { if (obj->IsNode()) { if (inClosedOkay || obj->IsOpenNode()) { if (this->IsMutable() || !inMutable) outObject = obj; else this->NonMutableNodeError(ev); } else this->NonOpenObjectError(ev); } else this->NonNodeObjectError(ev); } else if (!inClosedOkay) this->NilHandleObjectError(ev); } else this->NewBadMagicHandleError(ev, inMagicType); } else this->NewDownHandleError(ev); MORK_ASSERT(outObject || inClosedOkay); return outObject; } morkEnv* morkHandle::CanUseHandle(nsIMdbEnv* mev, mork_bool inMutable, mork_bool inClosedOkay, nsresult* outErr) const { morkEnv* outEnv = 0; morkEnv* ev = morkEnv::FromMdbEnv(mev); if (ev) { morkObject* obj = this->GetGoodHandleObject(ev, inMutable, /*magic*/ 0, inClosedOkay); if (obj) { outEnv = ev; } *outErr = ev->AsErr(); } MORK_ASSERT(outEnv || inClosedOkay); return outEnv; } // { ===== begin nsIMdbObject methods ===== // { ----- begin attribute methods ----- /*virtual*/ nsresult morkHandle::Handle_IsFrozenMdbObject( nsIMdbEnv* mev, mdb_bool* outIsReadonly) { nsresult outErr = NS_OK; mdb_bool readOnly = mdbBool_kTrue; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { readOnly = mHandle_Object->IsFrozen(); outErr = ev->AsErr(); } MORK_ASSERT(outIsReadonly); if (outIsReadonly) *outIsReadonly = readOnly; return outErr; } // same as nsIMdbPort::GetIsPortReadonly() when this object is inside a port. // } ----- end attribute methods ----- // { ----- begin factory methods ----- /*virtual*/ nsresult morkHandle::Handle_GetMdbFactory( nsIMdbEnv* mev, nsIMdbFactory** acqFactory) { nsresult outErr = NS_OK; nsIMdbFactory* handle = 0; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { morkFactory* factory = ev->mEnv_Factory; if (factory) { handle = factory; NS_ADDREF(handle); } else this->NilFactoryError(ev); outErr = ev->AsErr(); } MORK_ASSERT(acqFactory); if (acqFactory) *acqFactory = handle; return outErr; } // } ----- end factory methods ----- // { ----- begin ref counting for well-behaved cyclic graphs ----- /*virtual*/ nsresult morkHandle::Handle_GetWeakRefCount( nsIMdbEnv* mev, // weak refs mdb_count* outCount) { nsresult outErr = NS_OK; mdb_count count = 0; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { count = this->WeakRefsOnly(); outErr = ev->AsErr(); } MORK_ASSERT(outCount); if (outCount) *outCount = count; return outErr; } /*virtual*/ nsresult morkHandle::Handle_GetStrongRefCount( nsIMdbEnv* mev, // strong refs mdb_count* outCount) { nsresult outErr = NS_OK; mdb_count count = 0; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { count = this->StrongRefsOnly(); outErr = ev->AsErr(); } MORK_ASSERT(outCount); if (outCount) *outCount = count; return outErr; } /*virtual*/ nsresult morkHandle::Handle_AddWeakRef(nsIMdbEnv* mev) { nsresult outErr = NS_OK; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { this->AddWeakRef(ev); outErr = ev->AsErr(); } return outErr; } /*virtual*/ nsresult morkHandle::Handle_AddStrongRef(nsIMdbEnv* mev) { nsresult outErr = NS_OK; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kFalse, &outErr); if (ev) { this->AddStrongRef(ev); outErr = ev->AsErr(); } return outErr; } /*virtual*/ nsresult morkHandle::Handle_CutWeakRef(nsIMdbEnv* mev) { nsresult outErr = NS_OK; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { this->CutWeakRef(ev); outErr = ev->AsErr(); } return outErr; } /*virtual*/ nsresult morkHandle::Handle_CutStrongRef(nsIMdbEnv* mev) { nsresult outErr = NS_OK; morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { this->CutStrongRef(ev); outErr = ev->AsErr(); } return outErr; } /*virtual*/ nsresult morkHandle::Handle_CloseMdbObject(nsIMdbEnv* mev) // called at strong refs zero { // if only one ref, Handle_CutStrongRef will clean up better. if (mNode_Uses == 1) return Handle_CutStrongRef(mev); nsresult outErr = NS_OK; if (this->IsNode() && this->IsOpenNode()) { morkEnv* ev = CanUseHandle(mev, /*inMutable*/ morkBool_kFalse, /*inClosedOkay*/ morkBool_kTrue, &outErr); if (ev) { morkObject* object = mHandle_Object; if (object && object->IsNode() && object->IsOpenNode()) object->CloseMorkNode(ev); this->CloseMorkNode(ev); outErr = ev->AsErr(); } } return outErr; } /*virtual*/ nsresult morkHandle::Handle_IsOpenMdbObject(nsIMdbEnv* mev, mdb_bool* outOpen) { MORK_USED_1(mev); nsresult outErr = NS_OK; MORK_ASSERT(outOpen); if (outOpen) *outOpen = this->IsOpenNode(); return outErr; } // } ----- end ref counting ----- // } ===== end nsIMdbObject methods ===== // 456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789