Reenable test.
[wine-gecko.git] / db / mork / src / morkPool.cpp
blobf4c33233efe2fdc9816e8587d4a0f854f3d6def7
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
13 * License.
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.
22 * Contributor(s):
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 ***** */
38 #ifndef _MDB_
39 #include "mdb.h"
40 #endif
42 #ifndef _MORK_
43 #include "mork.h"
44 #endif
46 #ifndef _MORKNODE_
47 #include "morkNode.h"
48 #endif
50 #ifndef _MORKENV_
51 #include "morkEnv.h"
52 #endif
54 #ifndef _MORKPOOL_
55 #include "morkPool.h"
56 #endif
58 #ifndef _MORKATOM_
59 #include "morkAtom.h"
60 #endif
62 #ifndef _MORKHANDLE_
63 #include "morkHandle.h"
64 #endif
66 #ifndef _MORKCELL_
67 #include "morkCell.h"
68 #endif
70 #ifndef _MORKROW_
71 #include "morkRow.h"
72 #endif
74 #ifndef _MORKBLOB_
75 #include "morkBlob.h"
76 #endif
78 #ifndef _MORKDEQUE_
79 #include "morkDeque.h"
80 #endif
82 #ifndef _MORKZONE_
83 #include "morkZone.h"
84 #endif
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() )
96 this->MarkClosing();
97 this->ClosePool(ev);
98 this->MarkShut();
102 /*public virtual*/
103 morkPool::~morkPool() // assert ClosePool() executed earlier
105 MORK_ASSERT(this->IsShutNode());
108 /*public non-poly*/
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);
118 if ( ioSlotHeap )
119 mNode_Derived = morkDerived_kPool;
122 /*public non-poly*/
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 )
130 if ( ioSlotHeap )
132 // mPool_Heap is NOT refcounted:
133 // nsIMdbHeap_SlotStrongHeap(ioSlotHeap, ev, &mPool_Heap);
134 if ( ev->Good() )
135 mNode_Derived = morkDerived_kPool;
137 else
138 ev->NilPointerError();
141 /*public non-poly*/ void
142 morkPool::ClosePool(morkEnv* ev) // called by CloseMorkNode();
144 if ( this )
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();
155 morkLink* aLink;
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);
165 this->MarkShut();
167 else
168 this->NonNodeError(ev);
170 else
171 ev->NilPointerError();
174 // } ===== end morkNode methods =====
175 // ````` ````` ````` ````` `````
178 // alloc and free individual instances of handles (inside hand frames):
179 morkHandleFace*
180 morkPool::NewHandle(morkEnv* ev, mork_size inSize, morkZone* ioZone)
182 void* newBlock = 0;
183 if ( inSize <= sizeof(morkHandleFrame) )
185 morkLink* firstLink = mPool_FreeHandleFrames.RemoveFirst();
186 if ( firstLink )
188 newBlock = firstLink;
189 if ( mPool_FreeFramesCount )
190 --mPool_FreeFramesCount;
191 else
192 ev->NewWarning("mPool_FreeFramesCount underflow");
194 else
195 mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkHandleFrame),
196 (void**) &newBlock);
198 else
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*/
205 MORK_USED_1(ioZone);
206 #endif /*morkZone_CONFIG_ARENA*/
208 return (morkHandleFace*) newBlock;
211 void
212 morkPool::ZapHandle(morkEnv* ev, morkHandleFace* ioHandle)
214 if ( 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:
230 morkRow*
231 morkPool::NewRow(morkEnv* ev, morkZone* ioZone) // allocate a new row instance
233 morkRow* newRow = 0;
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*/
239 MORK_USED_1(ioZone);
240 mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkRow), (void**) &newRow);
241 #endif /*morkZone_CONFIG_ARENA*/
243 if ( newRow )
244 MORK_MEMSET(newRow, 0, sizeof(morkRow));
246 return newRow;
249 void
250 morkPool::ZapRow(morkEnv* ev, morkRow* ioRow,
251 morkZone* ioZone) // free old row instance
253 #ifdef morkZone_CONFIG_ARENA
254 if ( !ioRow )
255 ev->NilPointerWarning(); // a zone 'chip' cannot be freed
256 #else /*morkZone_CONFIG_ARENA*/
257 MORK_USED_1(ioZone);
258 if ( ioRow )
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)
264 morkCell*
265 morkPool::NewCells(morkEnv* ev, mork_size inSize,
266 morkZone* ioZone)
268 morkCell* newCells = 0;
270 mork_size size = inSize * sizeof(morkCell);
271 if ( size )
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*/
277 MORK_USED_1(ioZone);
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:
283 if ( newCells )
284 MORK_MEMSET(newCells, 0, size);
285 return newCells;
288 void
289 morkPool::ZapCells(morkEnv* ev, morkCell* ioVector, mork_size inSize,
290 morkZone* ioZone)
292 MORK_USED_1(inSize);
294 if ( ioVector )
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*/
300 MORK_USED_1(ioZone);
301 mPool_Heap->Free(ev->AsMdbEnv(), ioVector);
302 #endif /*morkZone_CONFIG_ARENA*/
306 // resize (grow or trim) cell vectors inside a containing row instance
307 mork_bool
308 morkPool::AddRowCells(morkEnv* ev, morkRow* ioRow, mork_size inNewSize,
309 morkZone* ioZone)
311 // note strong implementation similarity to morkArray::Grow()
313 MORK_USED_1(ioZone);
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);
322 if ( newCells )
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;
334 ++ioRow->mRow_Seed;
336 if ( oldCells )
337 this->ZapCells(ev, oldCells, fill, ioZone);
340 return ( ev->Good() && ioRow->mRow_Length >= inNewSize );
343 mork_bool
344 morkPool::CutRowCells(morkEnv* ev, morkRow* ioRow,
345 mork_size inNewSize,
346 morkZone* ioZone)
348 MORK_USED_1(ioZone);
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);
359 if ( newCells )
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
373 ++oldCells;
375 oldCells = ioRow->mRow_Cells;
376 ioRow->mRow_Cells = saveNewCells;
377 ioRow->mRow_Length = (mork_u2) inNewSize;
378 ++ioRow->mRow_Seed;
380 if ( oldCells )
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;
389 ++ioRow->mRow_Seed;
391 if ( oldCells )
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):
399 void
400 morkPool::ZapAtom(morkEnv* ev, morkAtom* ioAtom,
401 morkZone* ioZone) // any subclass (by kind)
403 #ifdef morkZone_CONFIG_ARENA
404 if ( !ioAtom )
405 ev->NilPointerWarning(); // a zone 'chip' cannot be freed
406 #else /*morkZone_CONFIG_ARENA*/
407 MORK_USED_1(ioZone);
408 if ( ioAtom )
409 mPool_Heap->Free(ev->AsMdbEnv(), ioAtom);
410 #endif /*morkZone_CONFIG_ARENA*/
413 morkOidAtom*
414 morkPool::NewRowOidAtom(morkEnv* ev, const mdbOid& inOid,
415 morkZone* ioZone)
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*/
423 MORK_USED_1(ioZone);
424 mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom),(void**) &newAtom);
425 #endif /*morkZone_CONFIG_ARENA*/
427 if ( newAtom )
428 newAtom->InitRowOidAtom(ev, inOid);
429 return newAtom;
432 morkOidAtom*
433 morkPool::NewTableOidAtom(morkEnv* ev, const mdbOid& inOid,
434 morkZone* ioZone)
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*/
442 MORK_USED_1(ioZone);
443 mPool_Heap->Alloc(ev->AsMdbEnv(), sizeof(morkOidAtom), (void**) &newAtom);
444 #endif /*morkZone_CONFIG_ARENA*/
445 if ( newAtom )
446 newAtom->InitTableOidAtom(ev, inOid);
447 return newAtom;
450 morkAtom*
451 morkPool::NewAnonAtom(morkEnv* ev, const morkBuf& inBuf,
452 mork_cscode inForm,
453 morkZone* ioZone)
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*/
468 MORK_USED_1(ioZone);
469 mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
470 #endif /*morkZone_CONFIG_ARENA*/
471 if ( newAtom )
473 if ( needBig )
474 ((morkBigAnonAtom*) newAtom)->InitBigAnonAtom(ev, inBuf, inForm);
475 else
476 ((morkWeeAnonAtom*) newAtom)->InitWeeAnonAtom(ev, inBuf);
478 return newAtom;
481 morkBookAtom*
482 morkPool::NewBookAtom(morkEnv* ev, const morkBuf& inBuf,
483 mork_cscode inForm, morkAtomSpace* ioSpace, mork_aid inAid,
484 morkZone* ioZone)
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*/
499 MORK_USED_1(ioZone);
500 mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
501 #endif /*morkZone_CONFIG_ARENA*/
502 if ( newAtom )
504 if ( needBig )
505 ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
506 inBuf, inForm, ioSpace, inAid);
507 else
508 ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
509 inBuf, ioSpace, inAid);
511 return newAtom;
514 morkBookAtom*
515 morkPool::NewBookAtomCopy(morkEnv* ev, const morkBigBookAtom& inAtom,
516 morkZone* ioZone)
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*/
534 MORK_USED_1(ioZone);
535 mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
536 #endif /*morkZone_CONFIG_ARENA*/
537 if ( newAtom )
539 morkBuf buf(inAtom.mBigBookAtom_Body, fill);
540 if ( needBig )
541 ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
542 buf, form, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
543 else
544 ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
545 buf, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
547 return newAtom;
550 morkBookAtom*
551 morkPool::NewFarBookAtomCopy(morkEnv* ev, const morkFarBookAtom& inAtom,
552 morkZone* ioZone)
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*/
570 MORK_USED_1(ioZone);
571 mPool_Heap->Alloc(ev->AsMdbEnv(), size, (void**) &newAtom);
572 #endif /*morkZone_CONFIG_ARENA*/
573 if ( newAtom )
575 morkBuf buf(inAtom.mFarBookAtom_Body, fill);
576 if ( needBig )
577 ((morkBigBookAtom*) newAtom)->InitBigBookAtom(ev,
578 buf, form, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
579 else
580 ((morkWeeBookAtom*) newAtom)->InitWeeBookAtom(ev,
581 buf, inAtom.mBookAtom_Space, inAtom.mBookAtom_Id);
583 return newAtom;
588 //3456789_123456789_123456789_123456789_123456789_123456789_123456789_123456789