1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: swcache.cxx,v $
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>
37 #include <swcache.hxx>
39 SV_IMPL_PTRARR(SwCacheObjArr
,SwCacheObj
*);
42 #define INCREMENT( nVar )
44 #define INCREMENT( nVar ) ++nVar
47 /*************************************************************************
51 |* Ersterstellung MA 23. Mar. 94
52 |* Letzte Aenderung MA 23. Mar. 94
54 |*************************************************************************/
64 ASSERT( !pLast
->GetNext(), "Last but not last." );
65 ASSERT( !pRealFirst
->GetPrev(), "First but not first." );
67 BOOL bFirstFound
= FALSE
;
68 SwCacheObj
*pObj
= pRealFirst
;
69 SwCacheObj
*pRekursive
= 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." );
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." );
93 #if !defined(PRODUCT) && defined(MADEBUG)
94 #define CHECK Check();
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
111 , const ByteString
&rNm
114 SwCacheObjArr( (BYTE
)nInitSize
, (BYTE
)nGrowSize
),
115 aFreePositions( 5, 5 ),
131 nAverageSeekCnt( 0 ),
133 nFlushedObjects( 0 ),
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() );
182 /*************************************************************************
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;
201 if ( pObj
->IsLocked() )
203 ASSERT( TRUE
, "Flushing locked objects." );
206 pRealFirst
= pFirst
= pLast
= pObj
;
207 pTmp
= pObj
->GetNext();
208 pObj
->SetNext( 0 ); pObj
->SetPrev( 0 );
212 { pLast
->SetNext( pObj
);
213 pObj
->SetPrev( pLast
);
215 pTmp
= pObj
->GetNext();
223 pTmp
= (SwCacheObj
*)pObj
;
224 pObj
= pTmp
->GetNext();
225 aFreePositions
.Insert( pTmp
->GetCachePos(), aFreePositions
.Count() );
226 *(pData
+ pTmp
->GetCachePos()) = (void*)0;
228 INCREMENT( nFlushedObjects
);
233 /*************************************************************************
237 |* Ersterstellung MA 15. Mar. 94
238 |* Letzte Aenderung MA 24. Apr. 95
240 |*************************************************************************/
243 void SwCache::ToTop( SwCacheObj
*pObj
)
247 //Objekt aus der LRU-Kette ausschneiden und am Anfang einfuegen.
248 if ( pRealFirst
== pObj
) //pFirst wurde vom Aufrufer geprueft!
254 { //Der erste wird eingetragen.
255 ASSERT( !pFirst
&& !pLast
, "First not first." );
256 pRealFirst
= pFirst
= pLast
= pObj
;
264 ASSERT( pObj
->GetPrev(), "Last but no Prev." );
265 pLast
= pObj
->GetPrev();
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
);
282 pRealFirst
= pFirst
= pObj
;
287 ASSERT( pFirst
, "ToTop, First ist not RealFirst an Empty." );
289 if ( pFirst
->GetPrev() )
291 pFirst
->GetPrev()->SetNext( pObj
);
292 pObj
->SetPrev( pFirst
->GetPrev() );
296 pFirst
->SetPrev( pObj
);
297 pObj
->SetNext( pFirst
);
303 /*************************************************************************
307 |* Ersterstellung MA 15. Mar. 94
308 |* Letzte Aenderung MA 22. Aug. 94
310 |*************************************************************************/
313 SwCacheObj
*SwCache::Get( const void *pOwner
, const USHORT nIndex
,
317 if ( 0 != (pRet
= nIndex
< Count() ? operator[]( nIndex
) : 0) )
319 if ( !pRet
->IsOwner( pOwner
) )
321 else if ( bToTop
&& pRet
!= pFirst
)
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
)
359 /*************************************************************************
363 |* Ersterstellung MA 15. Mar. 94
364 |* Letzte Aenderung MA 15. Mar. 94
366 |*************************************************************************/
369 void SwCache::DeleteObj( SwCacheObj
*pObj
)
372 ASSERT( !pObj
->IsLocked(), "SwCache::Delete: Object ist Locked." );
373 if ( pObj
->IsLocked() )
376 if ( pFirst
== pObj
)
378 if ( pFirst
->GetNext() )
379 pFirst
= pFirst
->GetNext();
381 pFirst
= pFirst
->GetPrev();
383 if ( pRealFirst
== pObj
)
384 pRealFirst
= pRealFirst
->GetNext();
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;
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
);
409 { SwCacheObjArr::Remove( i
, 1 );
413 pTmpObj
->SetCachePos( i
);
415 aFreePositions
.Remove( 0, aFreePositions
.Count() );
423 void SwCache::Delete( const void *pOwner, const USHORT nIndex )
425 INCREMENT( nDelete );
427 if ( 0 != (pObj = Get( pOwner, nIndex, FALSE )) )
434 void SwCache::Delete( const void *pOwner
)
436 INCREMENT( nDelete
);
438 if ( 0 != (pObj
= Get( pOwner
, BOOL(FALSE
) )) )
443 /*************************************************************************
447 |* Ersterstellung MA 15. Mar. 94
448 |* Letzte Aenderung MA 20. Sep. 94
450 |*************************************************************************/
453 BOOL
SwCache::Insert( SwCacheObj
*pNew
)
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
);
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
);
477 INCREMENT( nReplace
);
478 //Der letzte des LRU fliegt raus.
479 SwCacheObj
*pObj
= pLast
;
481 while ( pObj
&& pObj
->IsLocked() )
482 pObj
= pObj
->GetPrev();
485 ASSERT( FALSE
, "Cache overflow." );
489 nPos
= pObj
->GetCachePos();
491 { ASSERT( pObj
->GetPrev(), "Last but no Prev" );
492 pLast
= pObj
->GetPrev();
497 if ( pObj
->GetPrev() )
498 pObj
->GetPrev()->SetNext( pObj
->GetNext() );
499 if ( pObj
->GetNext() )
500 pObj
->GetNext()->SetPrev( pObj
->GetPrev() );
503 *(pData
+ nPos
) = pNew
;
505 pNew
->SetCachePos( nPos
);
507 //Anstelle von ToTop, einfach als pFirst einfuegen.
511 if ( pFirst
->GetPrev() )
512 { pFirst
->GetPrev()->SetNext( pNew
);
513 pNew
->SetPrev( pFirst
->GetPrev() );
515 pFirst
->SetPrev( pNew
);
516 pNew
->SetNext( pFirst
);
519 { ASSERT( !pLast
, "Last but no First." );
522 if ( pFirst
== pRealFirst
)
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
) )
547 for ( USHORT i
= 0; i
< Count() && i
< nOfst
; ++i
)
549 if ( pFirst
->GetNext() && pFirst
->GetNext()->GetNext() )
550 pFirst
= pFirst
->GetNext();
557 /*************************************************************************
559 |* SwCacheObj::SwCacheObj()
561 |* Ersterstellung MA 15. Mar. 94
562 |* Letzte Aenderung MA 24. Nov. 95
564 |*************************************************************************/
567 SwCacheObj::SwCacheObj( const void *pOwn
) :
570 nCachePos( USHRT_MAX
),
578 SwCacheObj::~SwCacheObj()
582 /*************************************************************************
584 |* SwCacheObj::SetLock(), Unlock()
586 |* Ersterstellung MA 15. Mar. 94
587 |* Letzte Aenderung MA 15. Mar. 94
589 |*************************************************************************/
595 void SwCacheObj::Lock()
597 ASSERT( nLock
< UCHAR_MAX
, "To many Locks for CacheObject." );
603 void SwCacheObj::Unlock()
605 ASSERT( nLock
, "No more Locks available." );
611 SwCacheAccess::~SwCacheAccess()
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." );
632 if ( !rCache
.Insert( pObj
) )
641 /*************************************************************************
643 |* SwCacheAccess::IsAvailable()
645 |* Ersterstellung MA 23. Mar. 94
646 |* Letzte Aenderung MA 23. Mar. 94
648 |*************************************************************************/
651 BOOL
SwCacheAccess::IsAvailable() const