/* -*- 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 _MORKNODE_ #include "morkNode.h" #endif #ifndef _MORKENV_ #include "morkEnv.h" #endif #ifndef _MORKPOOL_ #include "morkPool.h" #endif #ifndef _MORKATOM_ #include "morkAtom.h" #endif #ifndef _MORKHANDLE_ #include "morkHandle.h" #endif #ifndef _MORKCELL_ #include "morkCell.h" #endif #ifndef _MORKROW_ #include "morkRow.h" #endif #ifndef _MORKBLOB_ #include "morkBlob.h" #endif #ifndef _MORKDEQUE_ #include "morkDeque.h" #endif #ifndef _MORKZONE_ #include "morkZone.h" #endif //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789 // ````` ````` ````` ````` ````` // { ===== begin morkNode interface ===== /*public virtual*/ void morkPool::CloseMorkNode(morkEnv* ev) // ClosePool() only if open { if ( this->IsOpenNode() ) { this->MarkClosing(); this->ClosePool(ev); this->MarkShut(); } } /*public virtual*/ morkPool::~morkPool() // assert ClosePool() executed earlier { MORK_ASSERT(this->IsShutNode()); } /*public non-poly*/ morkPool::morkPool(const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap) : morkNode(inUsage, ioHeap) , mPool_Heap( ioSlotHeap ) , mPool_UsedFramesCount( 0 ) , mPool_FreeFramesCount( 0 ) { // mPool_Heap is NOT refcounted MORK_ASSERT(ioSlotHeap); if ( ioSlotHeap ) mNode_Derived = morkDerived_kPool; } /*public non-poly*/ morkPool::morkPool(morkEnv* ev, const morkUsage& inUsage, nsIMdbHeap* ioHeap, nsIMdbHeap* ioSlotHeap) : morkNode(ev, inUsage, ioHeap) , mPool_Heap( ioSlotHeap ) , mPool_UsedFramesCount( 0 ) , mPool_FreeFramesCount( 0 ) { if ( ioSlotHeap ) { // mPool_Heap is NOT refcounted: // nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mPool_Heap); if ( ev->Good() ) mNode_Derived = morkDerived_kPool; } else ev->NilPointerError(); } /*public non-poly*/ void morkPool::ClosePool(morkEnv* ev) // called by CloseMorkNode(); { if ( this->IsNode() ) { #ifdef morkZone_CONFIG_ARENA #else /*morkZone_CONFIG_ARENA*/ //MORK_USED_1(ioZone); #endif /*morkZone_CONFIG_ARENA*/ nsIMdbHeap* heap = mPool_Heap; nsIMdbEnv* mev = ev->AsMdbEnv(); morkLink* aLink; morkDeque* d = &mPool_FreeHandleFrames; while ( (aLink = d->RemoveFirst()) != 0 ) heap->Free(mev, aLink); // if the pool's closed, get rid of the frames in use too. d = &mPool_UsedHandleFrames; while ( (aLink = d->RemoveFirst()) != 0 ) heap->Free(mev, aLink); this->MarkShut(); } else this->NonNodeError(ev); } // } ===== end morkNode methods ===== // ````` ````` ````` ````` ````` // alloc and free individual instances of handles (inside hand frames): morkHandleFace* morkPool::NewHandle(morkEnv* ev, mork_size inSize, morkZone* ioZone) { void* newBlock = 0; if ( inSize <= sizeof(morkHandleFrame) ) { morkLink* firstLink = mPool_FreeHandleFrames.RemoveFirst(); if ( firstLink ) { newBlock = firstLink; if ( mPool_FreeFramesCount ) --mPool_FreeFramesCount; else ev->NewWarning("mPool_FreeFramesCount underflow"); } else mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkHandleFrame), (void**) &newBlock); } else { ev->NewWarning("inSize > sizeof(morkHandleFrame)"); mPool_Heap->Alloc(ev->AsMdbEnv(), inSize, (void**) &newBlock); } #ifdef morkZone_CONFIG_ARENA #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); #endif /*morkZone_CONFIG_ARENA*/ return (morkHandleFace*) newBlock; } void morkPool::ZapHandle(morkEnv* ev, morkHandleFace* ioHandle) { if ( ioHandle ) { morkLink* handleLink = (morkLink*) ioHandle; mPool_FreeHandleFrames.AddLast(handleLink); ++mPool_FreeFramesCount; // lets free all handles to track down leaks // - uncomment out next 3 lines, comment out above 2 // nsIMdbHeap* heap = mPool_Heap; // nsIMdbEnv* mev = ev->AsMdbEnv(); // heap->Free(mev, handleLink); } } // alloc and free individual instances of rows: morkRow* morkPool::NewRow(morkEnv* ev, morkZone* ioZone) // allocate a new row instance { morkRow* newRow = 0; #ifdef morkZone_CONFIG_ARENA // a zone 'chip' remembers no size, and so cannot be deallocated: newRow = (morkRow*) ioZone->ZoneNewChip(ev, sizeof(morkRow)); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkRow), (void**) &newRow); #endif /*morkZone_CONFIG_ARENA*/ if ( newRow ) MORK_MEMSET(newRow, 0, sizeof(morkRow)); return newRow; } void morkPool::ZapRow(morkEnv* ev, morkRow* ioRow, morkZone* ioZone) // free old row instance { #ifdef morkZone_CONFIG_ARENA if ( !ioRow ) ev->NilPointerWarning(); // a zone 'chip' cannot be freed #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); if ( ioRow ) mPool_Heap->Free(ev->AsMdbEnv(), ioRow); #endif /*morkZone_CONFIG_ARENA*/ } // alloc and free entire vectors of cells (not just one cell at a time) morkCell* morkPool::NewCells(morkEnv* ev, mork_size inSize, morkZone* ioZone) { morkCell* newCells = 0; mork_size size = inSize * sizeof(morkCell); if ( size ) { #ifdef morkZone_CONFIG_ARENA // a zone 'run' knows its size, and can indeed be deallocated: newCells = (morkCell*) ioZone->ZoneNewRun(ev, size); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newCells); #endif /*morkZone_CONFIG_ARENA*/ } // note morkAtom depends on having nil stored in all new mCell_Atom slots: if ( newCells ) MORK_MEMSET(newCells, 0, size); return newCells; } void morkPool::ZapCells(morkEnv* ev, morkCell* ioVector, mork_size inSize, morkZone* ioZone) { MORK_USED_1(inSize); if ( ioVector ) { #ifdef morkZone_CONFIG_ARENA // a zone 'run' knows its size, and can indeed be deallocated: ioZone->ZoneZapRun(ev, ioVector); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Free(ev->AsMdbEnv(), ioVector); #endif /*morkZone_CONFIG_ARENA*/ } } // resize (grow or trim) cell vectors inside a containing row instance mork_bool morkPool::AddRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize, morkZone* ioZone) { // note strong implementation similarity to morkArray::Grow() MORK_USED_1(ioZone); #ifdef morkZone_CONFIG_ARENA #else /*morkZone_CONFIG_ARENA*/ #endif /*morkZone_CONFIG_ARENA*/ mork_fill fill = ioRow->mRow_Length; if ( ev->Good() && fill < inNewSize ) // need more cells? { morkCell* newCells = this->NewCells(ev, inNewSize, ioZone); if ( newCells ) { morkCell* c = newCells; // for iterating during copy morkCell* oldCells = ioRow->mRow_Cells; morkCell* end = oldCells + fill; // copy all the old cells while ( oldCells < end ) { *c++ = *oldCells++; // bitwise copy each old cell struct } oldCells = ioRow->mRow_Cells; ioRow->mRow_Cells = newCells; ioRow->mRow_Length = (mork_u2) inNewSize; ++ioRow->mRow_Seed; if ( oldCells ) this->ZapCells(ev, oldCells, fill, ioZone); } } return ( ev->Good() && ioRow->mRow_Length >= inNewSize ); } mork_bool morkPool::CutRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize, morkZone* ioZone) { MORK_USED_1(ioZone); #ifdef morkZone_CONFIG_ARENA #else /*morkZone_CONFIG_ARENA*/ #endif /*morkZone_CONFIG_ARENA*/ mork_fill fill = ioRow->mRow_Length; if ( ev->Good() && fill > inNewSize ) // need fewer cells? { if ( inNewSize ) // want any row cells at all? { morkCell* newCells = this->NewCells(ev, inNewSize, ioZone); if ( newCells ) { morkCell* saveNewCells = newCells; // Keep newcell pos morkCell* oldCells = ioRow->mRow_Cells; morkCell* oldEnd = oldCells + fill; // one past all old cells morkCell* newEnd = oldCells + inNewSize; // copy only kept old cells while ( oldCells < newEnd ) { *newCells++ = *oldCells++; // bitwise copy each old cell struct } while ( oldCells < oldEnd ) { if ( oldCells->mCell_Atom ) // need to unref old cell atom? oldCells->SetAtom(ev, (morkAtom*) 0, this); // unref cell atom ++oldCells; } oldCells = ioRow->mRow_Cells; ioRow->mRow_Cells = saveNewCells; ioRow->mRow_Length = (mork_u2) inNewSize; ++ioRow->mRow_Seed; if ( oldCells ) this->ZapCells(ev, oldCells, fill, ioZone); } } else // get rid of all row cells { morkCell* oldCells = ioRow->mRow_Cells; ioRow->mRow_Cells = 0; ioRow->mRow_Length = 0; ++ioRow->mRow_Seed; if ( oldCells ) this->ZapCells(ev, oldCells, fill, ioZone); } } return ( ev->Good() && ioRow->mRow_Length <= inNewSize ); } // alloc & free individual instances of atoms (lots of atom subclasses): void morkPool::ZapAtom(morkEnv* ev, morkAtom* ioAtom, morkZone* ioZone) // any subclass (by kind) { #ifdef morkZone_CONFIG_ARENA if ( !ioAtom ) ev->NilPointerWarning(); // a zone 'chip' cannot be freed #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); if ( ioAtom ) mPool_Heap->Free(ev->AsMdbEnv(), ioAtom); #endif /*morkZone_CONFIG_ARENA*/ } morkOidAtom* morkPool::NewRowOidAtom(morkEnv* ev, const mdbOid& inOid, morkZone* ioZone) { morkOidAtom* newAtom = 0; #ifdef morkZone_CONFIG_ARENA // a zone 'chip' remembers no size, and so cannot be deallocated: newAtom = (morkOidAtom*) ioZone->ZoneNewChip(ev, sizeof(morkOidAtom)); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom),(void**) &newAtom); #endif /*morkZone_CONFIG_ARENA*/ if ( newAtom ) newAtom->InitRowOidAtom(ev, inOid); return newAtom; } morkOidAtom* morkPool::NewTableOidAtom(morkEnv* ev, const mdbOid& inOid, morkZone* ioZone) { morkOidAtom* newAtom = 0; #ifdef morkZone_CONFIG_ARENA // a zone 'chip' remembers no size, and so cannot be deallocated: newAtom = (morkOidAtom*) ioZone->ZoneNewChip(ev, sizeof(morkOidAtom)); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom), (void**) &newAtom); #endif /*morkZone_CONFIG_ARENA*/ if ( newAtom ) newAtom->InitTableOidAtom(ev, inOid); return newAtom; } morkAtom* morkPool::NewAnonAtom(morkEnv* ev, const morkBuf& inBuf, mork_cscode inForm, morkZone* ioZone) // if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee' // anon atom will be created, and otherwise a 'big' anon atom. { morkAtom* newAtom = 0; mork_bool needBig = ( inForm || inBuf.mBuf_Fill > 255 ); mork_size size = ( needBig )? morkBigAnonAtom::SizeForFill(inBuf.mBuf_Fill) : morkWeeAnonAtom::SizeForFill(inBuf.mBuf_Fill); #ifdef morkZone_CONFIG_ARENA // a zone 'chip' remembers no size, and so cannot be deallocated: newAtom = (morkAtom*) ioZone->ZoneNewChip(ev, size); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom); #endif /*morkZone_CONFIG_ARENA*/ if ( newAtom ) { if ( needBig ) ((morkBigAnonAtom*) newAtom)->InitBigAnonAtom(ev, inBuf, inForm); else ((morkWeeAnonAtom*) newAtom)->InitWeeAnonAtom(ev, inBuf); } return newAtom; } morkBookAtom* morkPool::NewBookAtom(morkEnv* ev, const morkBuf& inBuf, mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid, morkZone* ioZone) // if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee' // book atom will be created, and otherwise a 'big' book atom. { morkBookAtom* newAtom = 0; mork_bool needBig = ( inForm || inBuf.mBuf_Fill > 255 ); mork_size size = ( needBig )? morkBigBookAtom::SizeForFill(inBuf.mBuf_Fill) : morkWeeBookAtom::SizeForFill(inBuf.mBuf_Fill); #ifdef morkZone_CONFIG_ARENA // a zone 'chip' remembers no size, and so cannot be deallocated: newAtom = (morkBookAtom*) ioZone->ZoneNewChip(ev, size); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom); #endif /*morkZone_CONFIG_ARENA*/ if ( newAtom ) { if ( needBig ) ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev, inBuf, inForm, ioSpace, inAid); else ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev, inBuf, ioSpace, inAid); } return newAtom; } morkBookAtom* morkPool::NewBookAtomCopy(morkEnv* ev, const morkBigBookAtom& inAtom, morkZone* ioZone) // make the smallest kind of book atom that can hold content in inAtom. // The inAtom parameter is often expected to be a staged book atom in // the store, which was used to search an atom space for existing atoms. { morkBookAtom* newAtom = 0; mork_cscode form = inAtom.mBigBookAtom_Form; mork_fill fill = inAtom.mBigBookAtom_Size; mork_bool needBig = ( form || fill > 255 ); mork_size size = ( needBig )? morkBigBookAtom::SizeForFill(fill) : morkWeeBookAtom::SizeForFill(fill); #ifdef morkZone_CONFIG_ARENA // a zone 'chip' remembers no size, and so cannot be deallocated: newAtom = (morkBookAtom*) ioZone->ZoneNewChip(ev, size); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom); #endif /*morkZone_CONFIG_ARENA*/ if ( newAtom ) { morkBuf buf(inAtom.mBigBookAtom_Body, fill); if ( needBig ) ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev, buf, form, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id); else ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev, buf, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id); } return newAtom; } morkBookAtom* morkPool::NewFarBookAtomCopy(morkEnv* ev, const morkFarBookAtom& inAtom, morkZone* ioZone) // make the smallest kind of book atom that can hold content in inAtom. // The inAtom parameter is often expected to be a staged book atom in // the store, which was used to search an atom space for existing atoms. { morkBookAtom* newAtom = 0; mork_cscode form = inAtom.mFarBookAtom_Form; mork_fill fill = inAtom.mFarBookAtom_Size; mork_bool needBig = ( form || fill > 255 ); mork_size size = ( needBig )? morkBigBookAtom::SizeForFill(fill) : morkWeeBookAtom::SizeForFill(fill); #ifdef morkZone_CONFIG_ARENA // a zone 'chip' remembers no size, and so cannot be deallocated: newAtom = (morkBookAtom*) ioZone->ZoneNewChip(ev, size); #else /*morkZone_CONFIG_ARENA*/ MORK_USED_1(ioZone); mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom); #endif /*morkZone_CONFIG_ARENA*/ if ( newAtom ) { morkBuf buf(inAtom.mFarBookAtom_Body, fill); if ( needBig ) ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev, buf, form, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id); else ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev, buf, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id); } return newAtom; } //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789