Update ooo320-m1
[ooovba.git] / sw / source / core / bastyp / swcache.cxx
blob3d24c327f2a24cba94b4362f67c89eb89e12e06c
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swcache.cxx,v $
10 * $Revision: 1.13 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_sw.hxx"
35 #include <tools/debug.hxx>
36 #include <errhdl.hxx>
37 #include <swcache.hxx>
39 SV_IMPL_PTRARR(SwCacheObjArr,SwCacheObj*);
41 #ifdef PRODUCT
42 #define INCREMENT( nVar )
43 #else
44 #define INCREMENT( nVar ) ++nVar
45 #endif
47 /*************************************************************************
49 |* SwCache::Check()
51 |* Ersterstellung MA 23. Mar. 94
52 |* Letzte Aenderung MA 23. Mar. 94
54 |*************************************************************************/
56 #ifndef PRODUCT
58 void SwCache::Check()
60 if ( !pRealFirst )
61 return;
63 //Konsistenspruefung.
64 ASSERT( !pLast->GetNext(), "Last but not last." );
65 ASSERT( !pRealFirst->GetPrev(), "First but not first." );
66 USHORT nCnt = 0;
67 BOOL bFirstFound = FALSE;
68 SwCacheObj *pObj = pRealFirst;
69 SwCacheObj *pRekursive = pObj;
70 while ( pObj )
72 //Das Objekt muss auch auf dem Rueckwaertsweg gefunden werden.
73 SwCacheObj *pTmp = pLast;
74 while ( pTmp && pTmp != pObj )
75 pTmp = pTmp->GetPrev();
76 ASSERT( pTmp, "Objekt not found." );
78 ++nCnt;
79 if ( pObj == pFirst )
80 bFirstFound = TRUE;
81 if ( !pObj->GetNext() )
82 ASSERT( pObj == pLast, "Last not Found." );
83 pObj = pObj->GetNext();
84 ASSERT( pObj != pRekursive, "Recursion in SwCache." );
86 ASSERT( bFirstFound, "First not Found." );
87 ASSERT( (nCnt + aFreePositions.Count()) == Count(), "Lost Chain." );
88 if ( Count() == nCurMax )
89 ASSERT( (nCurMax - nCnt) == aFreePositions.Count(), "Lost FreePositions." );
91 #endif
93 #if !defined(PRODUCT) && defined(MADEBUG)
94 #define CHECK Check();
95 #else
96 #define CHECK
97 #endif
99 /*************************************************************************
101 |* SwCache::SwCache(), ~SwCache()
103 |* Ersterstellung MA 15. Mar. 94
104 |* Letzte Aenderung MA 15. Mar. 94
106 |*************************************************************************/
109 SwCache::SwCache( const USHORT nInitSize, const USHORT nGrowSize
110 #ifndef PRODUCT
111 , const ByteString &rNm
112 #endif
114 SwCacheObjArr( (BYTE)nInitSize, (BYTE)nGrowSize ),
115 aFreePositions( 5, 5 ),
116 pRealFirst( 0 ),
117 pFirst( 0 ),
118 pLast( 0 ),
119 nMax( nInitSize ),
120 nCurMax( nInitSize )
121 #ifndef PRODUCT
122 , aName( rNm ),
123 nAppend( 0 ),
124 nInsertFree( 0 ),
125 nReplace( 0 ),
126 nGetSuccess( 0 ),
127 nGetFail( 0 ),
128 nToTop( 0 ),
129 nDelete( 0 ),
130 nGetSeek( 0 ),
131 nAverageSeekCnt( 0 ),
132 nFlushCnt( 0 ),
133 nFlushedObjects( 0 ),
134 nIncreaseMax( 0 ),
135 nDecreaseMax( 0 )
136 #endif
140 #ifndef PRODUCT
143 SwCache::~SwCache()
145 #if OSL_DEBUG_LEVEL > 1
147 ByteString sOut( aName ); sOut += '\n';
148 (( sOut += "Anzahl neuer Eintraege: " )
149 += ByteString::CreateFromInt32( nAppend ))+= '\n';
150 (( sOut += "Anzahl Insert auf freie Plaetze: " )
151 += ByteString::CreateFromInt32( nInsertFree ))+= '\n';
152 (( sOut += "Anzahl Ersetzungen: " )
153 += ByteString::CreateFromInt32( nReplace ))+= '\n';
154 (( sOut += "Anzahl Erfolgreicher Get's: " )
155 += ByteString::CreateFromInt32( nGetSuccess ))+= '\n';
156 (( sOut += "Anzahl Fehlgeschlagener Get's: " )
157 += ByteString::CreateFromInt32( nGetFail ))+= '\n';
158 (( sOut += "Anzahl Umsortierungen (LRU): " )
159 += ByteString::CreateFromInt32( nToTop ))+= '\n';
160 (( sOut += "Anzahl Loeschungen: " )
161 += ByteString::CreateFromInt32( nDelete ))+= '\n';
162 (( sOut += "Anzahl Get's ohne Index: " )
163 += ByteString::CreateFromInt32( nGetSeek ))+= '\n';
164 (( sOut += "Anzahl Seek fuer Get ohne Index: " )
165 += ByteString::CreateFromInt32( nAverageSeekCnt ))+= '\n';
166 (( sOut += "Anzahl Flush-Aufrufe: " )
167 += ByteString::CreateFromInt32( nFlushCnt ))+= '\n';
168 (( sOut += "Anzahl geflush'ter Objekte: " )
169 += ByteString::CreateFromInt32( nFlushedObjects ))+= '\n';
170 (( sOut += "Anzahl Cache-Erweiterungen: " )
171 += ByteString::CreateFromInt32( nIncreaseMax ))+= '\n';
172 (( sOut += "Anzahl Cache-Verkleinerungen: " )
173 += ByteString::CreateFromInt32( nDecreaseMax ))+= '\n';
175 DBG_ERROR( sOut.GetBuffer() );
177 Check();
178 #endif
180 #endif
182 /*************************************************************************
184 |* SwCache::Flush()
186 |* Ersterstellung MA 15. Mar. 94
187 |* Letzte Aenderung MA 15. Mar. 94
189 |*************************************************************************/
192 void SwCache::Flush( const BYTE )
194 INCREMENT( nFlushCnt );
195 SwCacheObj *pObj = pRealFirst;
196 pRealFirst = pFirst = pLast = 0;
197 SwCacheObj *pTmp;
198 while ( pObj )
200 #ifndef PRODUCT
201 if ( pObj->IsLocked() )
203 ASSERT( TRUE, "Flushing locked objects." );
204 if ( !pRealFirst )
206 pRealFirst = pFirst = pLast = pObj;
207 pTmp = pObj->GetNext();
208 pObj->SetNext( 0 ); pObj->SetPrev( 0 );
209 pObj = pTmp;
211 else
212 { pLast->SetNext( pObj );
213 pObj->SetPrev( pLast );
214 pLast = pObj;
215 pTmp = pObj->GetNext();
216 pObj->SetNext( 0 );
217 pObj = pTmp;
220 else
221 #endif
223 pTmp = (SwCacheObj*)pObj;
224 pObj = pTmp->GetNext();
225 aFreePositions.Insert( pTmp->GetCachePos(), aFreePositions.Count() );
226 *(pData + pTmp->GetCachePos()) = (void*)0;
227 delete pTmp;
228 INCREMENT( nFlushedObjects );
233 /*************************************************************************
235 |* SwCache::ToTop()
237 |* Ersterstellung MA 15. Mar. 94
238 |* Letzte Aenderung MA 24. Apr. 95
240 |*************************************************************************/
243 void SwCache::ToTop( SwCacheObj *pObj )
245 INCREMENT( nToTop );
247 //Objekt aus der LRU-Kette ausschneiden und am Anfang einfuegen.
248 if ( pRealFirst == pObj ) //pFirst wurde vom Aufrufer geprueft!
249 { CHECK;
250 return;
253 if ( !pRealFirst )
254 { //Der erste wird eingetragen.
255 ASSERT( !pFirst && !pLast, "First not first." );
256 pRealFirst = pFirst = pLast = pObj;
257 CHECK;
258 return;
261 //Ausschneiden.
262 if ( pObj == pLast )
264 ASSERT( pObj->GetPrev(), "Last but no Prev." );
265 pLast = pObj->GetPrev();
266 pLast->SetNext( 0 );
268 else
270 if ( pObj->GetNext() )
271 pObj->GetNext()->SetPrev( pObj->GetPrev() );
272 if ( pObj->GetPrev() )
273 pObj->GetPrev()->SetNext( pObj->GetNext() );
276 //Am (virtuellen) Anfang einfuegen.
277 if ( pRealFirst == pFirst )
279 pRealFirst->SetPrev( pObj );
280 pObj->SetNext( pRealFirst );
281 pObj->SetPrev( 0 );
282 pRealFirst = pFirst = pObj;
283 CHECK;
285 else
287 ASSERT( pFirst, "ToTop, First ist not RealFirst an Empty." );
289 if ( pFirst->GetPrev() )
291 pFirst->GetPrev()->SetNext( pObj );
292 pObj->SetPrev( pFirst->GetPrev() );
294 else
295 pObj->SetPrev( 0 );
296 pFirst->SetPrev( pObj );
297 pObj->SetNext( pFirst );
298 pFirst = pObj;
299 CHECK;
303 /*************************************************************************
305 |* SwCache::Get()
307 |* Ersterstellung MA 15. Mar. 94
308 |* Letzte Aenderung MA 22. Aug. 94
310 |*************************************************************************/
313 SwCacheObj *SwCache::Get( const void *pOwner, const USHORT nIndex,
314 const BOOL bToTop )
316 SwCacheObj *pRet;
317 if ( 0 != (pRet = nIndex < Count() ? operator[]( nIndex ) : 0) )
319 if ( !pRet->IsOwner( pOwner ) )
320 pRet = 0;
321 else if ( bToTop && pRet != pFirst )
322 ToTop( pRet );
325 #ifndef PRODUCT
326 if ( pRet )
327 ++nGetSuccess;
328 else
329 ++nGetFail;
330 #endif
332 return pRet;
337 SwCacheObj *SwCache::Get( const void *pOwner, const BOOL bToTop )
339 SwCacheObj *pRet = pRealFirst;
340 while ( pRet && !pRet->IsOwner( pOwner ) )
342 INCREMENT( nAverageSeekCnt );
343 pRet = pRet->GetNext();
346 if ( bToTop && pRet && pRet != pFirst )
347 ToTop( pRet );
349 #ifndef PRODUCT
350 if ( pRet )
351 ++nGetSuccess;
352 else
353 ++nGetFail;
354 ++nGetSeek;
355 #endif
356 return pRet;
359 /*************************************************************************
361 |* SwCache::Delete()
363 |* Ersterstellung MA 15. Mar. 94
364 |* Letzte Aenderung MA 15. Mar. 94
366 |*************************************************************************/
369 void SwCache::DeleteObj( SwCacheObj *pObj )
371 CHECK;
372 ASSERT( !pObj->IsLocked(), "SwCache::Delete: Object ist Locked." );
373 if ( pObj->IsLocked() )
374 return;
376 if ( pFirst == pObj )
378 if ( pFirst->GetNext() )
379 pFirst = pFirst->GetNext();
380 else
381 pFirst = pFirst->GetPrev();
383 if ( pRealFirst == pObj )
384 pRealFirst = pRealFirst->GetNext();
385 if ( pLast == pObj )
386 pLast = pLast->GetPrev();
387 if ( pObj->GetPrev() )
388 pObj->GetPrev()->SetNext( pObj->GetNext() );
389 if ( pObj->GetNext() )
390 pObj->GetNext()->SetPrev( pObj->GetPrev() );
392 aFreePositions.Insert( pObj->GetCachePos(), aFreePositions.Count() );
393 *(pData + pObj->GetCachePos()) = (void*)0;
394 delete pObj;
396 CHECK;
397 if ( Count() > nCurMax &&
398 (nCurMax <= (Count() - aFreePositions.Count())) )
400 //Falls moeglich wieder verkleinern, dazu muessen allerdings ausreichend
401 //Freie Positionen bereitstehen.
402 //Unangenehmer Nebeneffekt ist, das die Positionen verschoben werden
403 //muessen, und die Eigentuemer der Objekte diese wahrscheinlich nicht
404 //wiederfinden werden.
405 for ( USHORT i = 0; i < Count(); ++i )
407 SwCacheObj *pTmpObj = operator[](i);
408 if ( !pTmpObj )
409 { SwCacheObjArr::Remove( i, 1 );
410 --i;
412 else
413 pTmpObj->SetCachePos( i );
415 aFreePositions.Remove( 0, aFreePositions.Count() );
417 CHECK;
423 void SwCache::Delete( const void *pOwner, const USHORT nIndex )
425 INCREMENT( nDelete );
426 SwCacheObj *pObj;
427 if ( 0 != (pObj = Get( pOwner, nIndex, FALSE )) )
428 DeleteObj( pObj );
434 void SwCache::Delete( const void *pOwner )
436 INCREMENT( nDelete );
437 SwCacheObj *pObj;
438 if ( 0 != (pObj = Get( pOwner, BOOL(FALSE) )) )
439 DeleteObj( pObj );
443 /*************************************************************************
445 |* SwCache::Insert()
447 |* Ersterstellung MA 15. Mar. 94
448 |* Letzte Aenderung MA 20. Sep. 94
450 |*************************************************************************/
453 BOOL SwCache::Insert( SwCacheObj *pNew )
455 CHECK;
456 ASSERT( !pNew->GetPrev() && !pNew->GetNext(), "New but not new." );
458 USHORT nPos;//Wird hinter den if's zum setzen am Obj benutzt.
459 if ( Count() < nCurMax )
461 //Es ist noch Platz frei, also einfach einfuegen.
462 INCREMENT( nAppend );
463 nPos = Count();
464 SwCacheObjArr::C40_INSERT( SwCacheObj, pNew, nPos );
466 else if ( aFreePositions.Count() )
468 //Es exitieren Platzhalter, also den letzten benutzen.
469 INCREMENT( nInsertFree );
470 const USHORT nFreePos = aFreePositions.Count() - 1;
471 nPos = aFreePositions[ nFreePos ];
472 *(pData + nPos) = pNew;
473 aFreePositions.Remove( nFreePos );
475 else
477 INCREMENT( nReplace );
478 //Der letzte des LRU fliegt raus.
479 SwCacheObj *pObj = pLast;
481 while ( pObj && pObj->IsLocked() )
482 pObj = pObj->GetPrev();
483 if ( !pObj )
485 ASSERT( FALSE, "Cache overflow." );
486 return FALSE;
489 nPos = pObj->GetCachePos();
490 if ( pObj == pLast )
491 { ASSERT( pObj->GetPrev(), "Last but no Prev" );
492 pLast = pObj->GetPrev();
493 pLast->SetNext( 0 );
495 else
497 if ( pObj->GetPrev() )
498 pObj->GetPrev()->SetNext( pObj->GetNext() );
499 if ( pObj->GetNext() )
500 pObj->GetNext()->SetPrev( pObj->GetPrev() );
502 delete pObj;
503 *(pData + nPos) = pNew;
505 pNew->SetCachePos( nPos );
507 //Anstelle von ToTop, einfach als pFirst einfuegen.
508 // ToTop( nPos );
509 if ( pFirst )
511 if ( pFirst->GetPrev() )
512 { pFirst->GetPrev()->SetNext( pNew );
513 pNew->SetPrev( pFirst->GetPrev() );
515 pFirst->SetPrev( pNew );
516 pNew->SetNext( pFirst );
518 else
519 { ASSERT( !pLast, "Last but no First." );
520 pLast = pNew;
522 if ( pFirst == pRealFirst )
523 pRealFirst = pNew;
524 pFirst = pNew;
526 CHECK;
527 return TRUE;
530 /*************************************************************************
532 |* SwCache::SetLRUOfst()
534 |* Ersterstellung MA 15. Mar. 94
535 |* Letzte Aenderung MA 15. Mar. 94
537 |*************************************************************************/
540 void SwCache::SetLRUOfst( const USHORT nOfst )
542 if ( !pRealFirst || ((Count() - aFreePositions.Count()) < nOfst) )
543 return;
545 CHECK;
546 pFirst = pRealFirst;
547 for ( USHORT i = 0; i < Count() && i < nOfst; ++i )
549 if ( pFirst->GetNext() && pFirst->GetNext()->GetNext() )
550 pFirst = pFirst->GetNext();
551 else
552 break;
554 CHECK;
557 /*************************************************************************
559 |* SwCacheObj::SwCacheObj()
561 |* Ersterstellung MA 15. Mar. 94
562 |* Letzte Aenderung MA 24. Nov. 95
564 |*************************************************************************/
567 SwCacheObj::SwCacheObj( const void *pOwn ) :
568 pNext( 0 ),
569 pPrev( 0 ),
570 nCachePos( USHRT_MAX ),
571 nLock( 0 ),
572 pOwner( pOwn )
578 SwCacheObj::~SwCacheObj()
582 /*************************************************************************
584 |* SwCacheObj::SetLock(), Unlock()
586 |* Ersterstellung MA 15. Mar. 94
587 |* Letzte Aenderung MA 15. Mar. 94
589 |*************************************************************************/
591 #ifndef PRODUCT
595 void SwCacheObj::Lock()
597 ASSERT( nLock < UCHAR_MAX, "To many Locks for CacheObject." );
598 ++nLock;
603 void SwCacheObj::Unlock()
605 ASSERT( nLock, "No more Locks available." );
606 --nLock;
608 #endif
611 SwCacheAccess::~SwCacheAccess()
613 if ( pObj )
614 pObj->Unlock();
617 /*************************************************************************
619 |* SwCacheAccess::Get()
621 |* Ersterstellung MA 15. Mar. 94
622 |* Letzte Aenderung MA 04. Apr. 95
624 |*************************************************************************/
627 void SwCacheAccess::_Get()
629 ASSERT( !pObj, "SwCacheAcces Obj already available." );
631 pObj = NewObj();
632 if ( !rCache.Insert( pObj ) )
634 delete pObj;
635 pObj = 0;
637 else
638 pObj->Lock();
641 /*************************************************************************
643 |* SwCacheAccess::IsAvailable()
645 |* Ersterstellung MA 23. Mar. 94
646 |* Letzte Aenderung MA 23. Mar. 94
648 |*************************************************************************/
651 BOOL SwCacheAccess::IsAvailable() const
653 return pObj != 0;