Source code

Revision control

Copy as Markdown

Other Tools

/* -*- 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