1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /* ***** BEGIN LICENSE BLOCK *****
3 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
5 * The contents of this file are subject to the Mozilla Public License Version
6 * 1.1 (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
8 * http://www.mozilla.org/MPL/
10 * Software distributed under the License is distributed on an "AS IS" basis,
11 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 * for the specific language governing rights and limitations under the
15 * The Original Code is mozilla.org code.
17 * The Initial Developer of the Original Code is
18 * Netscape Communications Corporation.
19 * Portions created by the Initial Developer are Copyright (C) 1999
20 * the Initial Developer. All Rights Reserved.
24 * Alternatively, the contents of this file may be used under the terms of
25 * either of the GNU General Public License Version 2 or later (the "GPL"),
26 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
27 * in which case the provisions of the GPL or the LGPL are applicable instead
28 * of those above. If you wish to allow use of your version of this file only
29 * under the terms of either the GPL or the LGPL, and not to allow others to
30 * use your version of this file under the terms of the MPL, indicate your
31 * decision by deleting the provisions above and replace them with the notice
32 * and other provisions required by the GPL or the LGPL. If you do not delete
33 * the provisions above, a recipient may use your version of this file under
34 * the terms of any one of the MPL, the GPL or the LGPL.
36 * ***** END LICENSE BLOCK ***** */
63 #include "morkHandle.h"
79 #include "morkDeque.h"
86 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789
88 // ````` ````` ````` ````` `````
89 // { ===== begin morkNode interface =====
91 /*public virtual*/ void
92 morkPool::CloseMorkNode(morkEnv
* ev
) // ClosePool() only if open
94 if ( this->IsOpenNode() )
103 morkPool::~morkPool() // assert ClosePool() executed earlier
105 MORK_ASSERT(this->IsShutNode());
109 morkPool::morkPool(const morkUsage
& inUsage
, nsIMdbHeap
* ioHeap
,
110 nsIMdbHeap
* ioSlotHeap
)
111 : morkNode(inUsage
, ioHeap
)
112 , mPool_Heap( ioSlotHeap
)
113 , mPool_UsedFramesCount( 0 )
114 , mPool_FreeFramesCount( 0 )
116 // mPool_Heap is NOT refcounted
117 MORK_ASSERT(ioSlotHeap
);
119 mNode_Derived
= morkDerived_kPool
;
123 morkPool::morkPool(morkEnv
* ev
,
124 const morkUsage
& inUsage
, nsIMdbHeap
* ioHeap
, nsIMdbHeap
* ioSlotHeap
)
125 : morkNode(ev
, inUsage
, ioHeap
)
126 , mPool_Heap( ioSlotHeap
)
127 , mPool_UsedFramesCount( 0 )
128 , mPool_FreeFramesCount( 0 )
132 // mPool_Heap is NOT refcounted:
133 // nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mPool_Heap);
135 mNode_Derived
= morkDerived_kPool
;
138 ev
->NilPointerError();
141 /*public non-poly*/ void
142 morkPool::ClosePool(morkEnv
* ev
) // called by CloseMorkNode();
146 if ( this->IsNode() )
148 #ifdef morkZone_CONFIG_ARENA
149 #else /*morkZone_CONFIG_ARENA*/
150 //MORK_USED_1(ioZone);
151 #endif /*morkZone_CONFIG_ARENA*/
153 nsIMdbHeap
* heap
= mPool_Heap
;
154 nsIMdbEnv
* mev
= ev
->AsMdbEnv();
156 morkDeque
* d
= &mPool_FreeHandleFrames
;
157 while ( (aLink
= d
->RemoveFirst()) != 0 )
158 heap
->Free(mev
, aLink
);
160 // if the pool's closed, get rid of the frames in use too.
161 d
= &mPool_UsedHandleFrames
;
162 while ( (aLink
= d
->RemoveFirst()) != 0 )
163 heap
->Free(mev
, aLink
);
168 this->NonNodeError(ev
);
171 ev
->NilPointerError();
174 // } ===== end morkNode methods =====
175 // ````` ````` ````` ````` `````
178 // alloc and free individual instances of handles (inside hand frames):
180 morkPool::NewHandle(morkEnv
* ev
, mork_size inSize
, morkZone
* ioZone
)
183 if ( inSize
<= sizeof(morkHandleFrame
) )
185 morkLink
* firstLink
= mPool_FreeHandleFrames
.RemoveFirst();
188 newBlock
= firstLink
;
189 if ( mPool_FreeFramesCount
)
190 --mPool_FreeFramesCount
;
192 ev
->NewWarning("mPool_FreeFramesCount underflow");
195 mPool_Heap
->Alloc(ev
->AsMdbEnv(), sizeof(morkHandleFrame
),
200 ev
->NewWarning("inSize > sizeof(morkHandleFrame)");
201 mPool_Heap
->Alloc(ev
->AsMdbEnv(), inSize
, (void**) &newBlock
);
203 #ifdef morkZone_CONFIG_ARENA
204 #else /*morkZone_CONFIG_ARENA*/
206 #endif /*morkZone_CONFIG_ARENA*/
208 return (morkHandleFace
*) newBlock
;
212 morkPool::ZapHandle(morkEnv
* ev
, morkHandleFace
* ioHandle
)
216 morkLink
* handleLink
= (morkLink
*) ioHandle
;
217 mPool_FreeHandleFrames
.AddLast(handleLink
);
218 ++mPool_FreeFramesCount
;
219 // lets free all handles to track down leaks
220 // - uncomment out next 3 lines, comment out above 2
221 // nsIMdbHeap* heap = mPool_Heap;
222 // nsIMdbEnv* mev = ev->AsMdbEnv();
223 // heap->Free(mev, handleLink);
229 // alloc and free individual instances of rows:
231 morkPool::NewRow(morkEnv
* ev
, morkZone
* ioZone
) // allocate a new row instance
235 #ifdef morkZone_CONFIG_ARENA
236 // a zone 'chip' remembers no size, and so cannot be deallocated:
237 newRow
= (morkRow
*) ioZone
->ZoneNewChip(ev
, sizeof(morkRow
));
238 #else /*morkZone_CONFIG_ARENA*/
240 mPool_Heap
->Alloc(ev
->AsMdbEnv(), sizeof(morkRow
), (void**) &newRow
);
241 #endif /*morkZone_CONFIG_ARENA*/
244 MORK_MEMSET(newRow
, 0, sizeof(morkRow
));
250 morkPool::ZapRow(morkEnv
* ev
, morkRow
* ioRow
,
251 morkZone
* ioZone
) // free old row instance
253 #ifdef morkZone_CONFIG_ARENA
255 ev
->NilPointerWarning(); // a zone 'chip' cannot be freed
256 #else /*morkZone_CONFIG_ARENA*/
259 mPool_Heap
->Free(ev
->AsMdbEnv(), ioRow
);
260 #endif /*morkZone_CONFIG_ARENA*/
263 // alloc and free entire vectors of cells (not just one cell at a time)
265 morkPool::NewCells(morkEnv
* ev
, mork_size inSize
,
268 morkCell
* newCells
= 0;
270 mork_size size
= inSize
* sizeof(morkCell
);
273 #ifdef morkZone_CONFIG_ARENA
274 // a zone 'run' knows its size, and can indeed be deallocated:
275 newCells
= (morkCell
*) ioZone
->ZoneNewRun(ev
, size
);
276 #else /*morkZone_CONFIG_ARENA*/
278 mPool_Heap
->Alloc(ev
->AsMdbEnv(), size
, (void**) &newCells
);
279 #endif /*morkZone_CONFIG_ARENA*/
282 // note morkAtom depends on having nil stored in all new mCell_Atom slots:
284 MORK_MEMSET(newCells
, 0, size
);
289 morkPool::ZapCells(morkEnv
* ev
, morkCell
* ioVector
, mork_size inSize
,
296 #ifdef morkZone_CONFIG_ARENA
297 // a zone 'run' knows its size, and can indeed be deallocated:
298 ioZone
->ZoneZapRun(ev
, ioVector
);
299 #else /*morkZone_CONFIG_ARENA*/
301 mPool_Heap
->Free(ev
->AsMdbEnv(), ioVector
);
302 #endif /*morkZone_CONFIG_ARENA*/
306 // resize (grow or trim) cell vectors inside a containing row instance
308 morkPool::AddRowCells(morkEnv
* ev
, morkRow
* ioRow
, mork_size inNewSize
,
311 // note strong implementation similarity to morkArray::Grow()
314 #ifdef morkZone_CONFIG_ARENA
315 #else /*morkZone_CONFIG_ARENA*/
316 #endif /*morkZone_CONFIG_ARENA*/
318 mork_fill fill
= ioRow
->mRow_Length
;
319 if ( ev
->Good() && fill
< inNewSize
) // need more cells?
321 morkCell
* newCells
= this->NewCells(ev
, inNewSize
, ioZone
);
324 morkCell
* c
= newCells
; // for iterating during copy
325 morkCell
* oldCells
= ioRow
->mRow_Cells
;
326 morkCell
* end
= oldCells
+ fill
; // copy all the old cells
327 while ( oldCells
< end
)
329 *c
++ = *oldCells
++; // bitwise copy each old cell struct
331 oldCells
= ioRow
->mRow_Cells
;
332 ioRow
->mRow_Cells
= newCells
;
333 ioRow
->mRow_Length
= (mork_u2
) inNewSize
;
337 this->ZapCells(ev
, oldCells
, fill
, ioZone
);
340 return ( ev
->Good() && ioRow
->mRow_Length
>= inNewSize
);
344 morkPool::CutRowCells(morkEnv
* ev
, morkRow
* ioRow
,
349 #ifdef morkZone_CONFIG_ARENA
350 #else /*morkZone_CONFIG_ARENA*/
351 #endif /*morkZone_CONFIG_ARENA*/
353 mork_fill fill
= ioRow
->mRow_Length
;
354 if ( ev
->Good() && fill
> inNewSize
) // need fewer cells?
356 if ( inNewSize
) // want any row cells at all?
358 morkCell
* newCells
= this->NewCells(ev
, inNewSize
, ioZone
);
361 morkCell
* saveNewCells
= newCells
; // Keep newcell pos
362 morkCell
* oldCells
= ioRow
->mRow_Cells
;
363 morkCell
* oldEnd
= oldCells
+ fill
; // one past all old cells
364 morkCell
* newEnd
= oldCells
+ inNewSize
; // copy only kept old cells
365 while ( oldCells
< newEnd
)
367 *newCells
++ = *oldCells
++; // bitwise copy each old cell struct
369 while ( oldCells
< oldEnd
)
371 if ( oldCells
->mCell_Atom
) // need to unref old cell atom?
372 oldCells
->SetAtom(ev
, (morkAtom
*) 0, this); // unref cell atom
375 oldCells
= ioRow
->mRow_Cells
;
376 ioRow
->mRow_Cells
= saveNewCells
;
377 ioRow
->mRow_Length
= (mork_u2
) inNewSize
;
381 this->ZapCells(ev
, oldCells
, fill
, ioZone
);
384 else // get rid of all row cells
386 morkCell
* oldCells
= ioRow
->mRow_Cells
;
387 ioRow
->mRow_Cells
= 0;
388 ioRow
->mRow_Length
= 0;
392 this->ZapCells(ev
, oldCells
, fill
, ioZone
);
395 return ( ev
->Good() && ioRow
->mRow_Length
<= inNewSize
);
398 // alloc & free individual instances of atoms (lots of atom subclasses):
400 morkPool::ZapAtom(morkEnv
* ev
, morkAtom
* ioAtom
,
401 morkZone
* ioZone
) // any subclass (by kind)
403 #ifdef morkZone_CONFIG_ARENA
405 ev
->NilPointerWarning(); // a zone 'chip' cannot be freed
406 #else /*morkZone_CONFIG_ARENA*/
409 mPool_Heap
->Free(ev
->AsMdbEnv(), ioAtom
);
410 #endif /*morkZone_CONFIG_ARENA*/
414 morkPool::NewRowOidAtom(morkEnv
* ev
, const mdbOid
& inOid
,
417 morkOidAtom
* newAtom
= 0;
419 #ifdef morkZone_CONFIG_ARENA
420 // a zone 'chip' remembers no size, and so cannot be deallocated:
421 newAtom
= (morkOidAtom
*) ioZone
->ZoneNewChip(ev
, sizeof(morkOidAtom
));
422 #else /*morkZone_CONFIG_ARENA*/
424 mPool_Heap
->Alloc(ev
->AsMdbEnv(), sizeof(morkOidAtom
),(void**) &newAtom
);
425 #endif /*morkZone_CONFIG_ARENA*/
428 newAtom
->InitRowOidAtom(ev
, inOid
);
433 morkPool::NewTableOidAtom(morkEnv
* ev
, const mdbOid
& inOid
,
436 morkOidAtom
* newAtom
= 0;
438 #ifdef morkZone_CONFIG_ARENA
439 // a zone 'chip' remembers no size, and so cannot be deallocated:
440 newAtom
= (morkOidAtom
*) ioZone
->ZoneNewChip(ev
, sizeof(morkOidAtom
));
441 #else /*morkZone_CONFIG_ARENA*/
443 mPool_Heap
->Alloc(ev
->AsMdbEnv(), sizeof(morkOidAtom
), (void**) &newAtom
);
444 #endif /*morkZone_CONFIG_ARENA*/
446 newAtom
->InitTableOidAtom(ev
, inOid
);
451 morkPool::NewAnonAtom(morkEnv
* ev
, const morkBuf
& inBuf
,
454 // if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
455 // anon atom will be created, and otherwise a 'big' anon atom.
457 morkAtom
* newAtom
= 0;
459 mork_bool needBig
= ( inForm
|| inBuf
.mBuf_Fill
> 255 );
460 mork_size size
= ( needBig
)?
461 morkBigAnonAtom::SizeForFill(inBuf
.mBuf_Fill
) :
462 morkWeeAnonAtom::SizeForFill(inBuf
.mBuf_Fill
);
464 #ifdef morkZone_CONFIG_ARENA
465 // a zone 'chip' remembers no size, and so cannot be deallocated:
466 newAtom
= (morkAtom
*) ioZone
->ZoneNewChip(ev
, size
);
467 #else /*morkZone_CONFIG_ARENA*/
469 mPool_Heap
->Alloc(ev
->AsMdbEnv(), size
, (void**) &newAtom
);
470 #endif /*morkZone_CONFIG_ARENA*/
474 ((morkBigAnonAtom
*) newAtom
)->InitBigAnonAtom(ev
, inBuf
, inForm
);
476 ((morkWeeAnonAtom
*) newAtom
)->InitWeeAnonAtom(ev
, inBuf
);
482 morkPool::NewBookAtom(morkEnv
* ev
, const morkBuf
& inBuf
,
483 mork_cscode inForm
, morkAtomSpace
* ioSpace
, mork_aid inAid
,
485 // if inForm is zero, and inBuf.mBuf_Fill is less than 256, then a 'wee'
486 // book atom will be created, and otherwise a 'big' book atom.
488 morkBookAtom
* newAtom
= 0;
490 mork_bool needBig
= ( inForm
|| inBuf
.mBuf_Fill
> 255 );
491 mork_size size
= ( needBig
)?
492 morkBigBookAtom::SizeForFill(inBuf
.mBuf_Fill
) :
493 morkWeeBookAtom::SizeForFill(inBuf
.mBuf_Fill
);
495 #ifdef morkZone_CONFIG_ARENA
496 // a zone 'chip' remembers no size, and so cannot be deallocated:
497 newAtom
= (morkBookAtom
*) ioZone
->ZoneNewChip(ev
, size
);
498 #else /*morkZone_CONFIG_ARENA*/
500 mPool_Heap
->Alloc(ev
->AsMdbEnv(), size
, (void**) &newAtom
);
501 #endif /*morkZone_CONFIG_ARENA*/
505 ((morkBigBookAtom
*) newAtom
)->InitBigBookAtom(ev
,
506 inBuf
, inForm
, ioSpace
, inAid
);
508 ((morkWeeBookAtom
*) newAtom
)->InitWeeBookAtom(ev
,
509 inBuf
, ioSpace
, inAid
);
515 morkPool::NewBookAtomCopy(morkEnv
* ev
, const morkBigBookAtom
& inAtom
,
517 // make the smallest kind of book atom that can hold content in inAtom.
518 // The inAtom parameter is often expected to be a staged book atom in
519 // the store, which was used to search an atom space for existing atoms.
521 morkBookAtom
* newAtom
= 0;
523 mork_cscode form
= inAtom
.mBigBookAtom_Form
;
524 mork_fill fill
= inAtom
.mBigBookAtom_Size
;
525 mork_bool needBig
= ( form
|| fill
> 255 );
526 mork_size size
= ( needBig
)?
527 morkBigBookAtom::SizeForFill(fill
) :
528 morkWeeBookAtom::SizeForFill(fill
);
530 #ifdef morkZone_CONFIG_ARENA
531 // a zone 'chip' remembers no size, and so cannot be deallocated:
532 newAtom
= (morkBookAtom
*) ioZone
->ZoneNewChip(ev
, size
);
533 #else /*morkZone_CONFIG_ARENA*/
535 mPool_Heap
->Alloc(ev
->AsMdbEnv(), size
, (void**) &newAtom
);
536 #endif /*morkZone_CONFIG_ARENA*/
539 morkBuf
buf(inAtom
.mBigBookAtom_Body
, fill
);
541 ((morkBigBookAtom
*) newAtom
)->InitBigBookAtom(ev
,
542 buf
, form
, inAtom
.mBookAtom_Space
, inAtom
.mBookAtom_Id
);
544 ((morkWeeBookAtom
*) newAtom
)->InitWeeBookAtom(ev
,
545 buf
, inAtom
.mBookAtom_Space
, inAtom
.mBookAtom_Id
);
551 morkPool::NewFarBookAtomCopy(morkEnv
* ev
, const morkFarBookAtom
& inAtom
,
553 // make the smallest kind of book atom that can hold content in inAtom.
554 // The inAtom parameter is often expected to be a staged book atom in
555 // the store, which was used to search an atom space for existing atoms.
557 morkBookAtom
* newAtom
= 0;
559 mork_cscode form
= inAtom
.mFarBookAtom_Form
;
560 mork_fill fill
= inAtom
.mFarBookAtom_Size
;
561 mork_bool needBig
= ( form
|| fill
> 255 );
562 mork_size size
= ( needBig
)?
563 morkBigBookAtom::SizeForFill(fill
) :
564 morkWeeBookAtom::SizeForFill(fill
);
566 #ifdef morkZone_CONFIG_ARENA
567 // a zone 'chip' remembers no size, and so cannot be deallocated:
568 newAtom
= (morkBookAtom
*) ioZone
->ZoneNewChip(ev
, size
);
569 #else /*morkZone_CONFIG_ARENA*/
571 mPool_Heap
->Alloc(ev
->AsMdbEnv(), size
, (void**) &newAtom
);
572 #endif /*morkZone_CONFIG_ARENA*/
575 morkBuf
buf(inAtom
.mFarBookAtom_Body
, fill
);
577 ((morkBigBookAtom
*) newAtom
)->InitBigBookAtom(ev
,
578 buf
, form
, inAtom
.mBookAtom_Space
, inAtom
.mBookAtom_Id
);
580 ((morkWeeBookAtom
*) newAtom
)->InitWeeBookAtom(ev
,
581 buf
, inAtom
.mBookAtom_Space
, inAtom
.mBookAtom_Id
);
588 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789