Branch data Line data Source code
1 : : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : : /*************************************************************************
3 : : *
4 : : * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 : : *
6 : : * Copyright 2000, 2010 Oracle and/or its affiliates.
7 : : *
8 : : * OpenOffice.org - a multi-platform office productivity suite
9 : : *
10 : : * This file is part of OpenOffice.org.
11 : : *
12 : : * OpenOffice.org is free software: you can redistribute it and/or modify
13 : : * it under the terms of the GNU Lesser General Public License version 3
14 : : * only, as published by the Free Software Foundation.
15 : : *
16 : : * OpenOffice.org is distributed in the hope that it will be useful,
17 : : * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 : : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 : : * GNU Lesser General Public License version 3 for more details
20 : : * (a copy is included in the LICENSE file that accompanied this code).
21 : : *
22 : : * You should have received a copy of the GNU Lesser General Public License
23 : : * version 3 along with OpenOffice.org. If not, see
24 : : * <http://www.openoffice.org/license.html>
25 : : * for a copy of the LGPLv3 License.
26 : : *
27 : : ************************************************************************/
28 : : #ifndef _SWCACHE_HXX
29 : : #define _SWCACHE_HXX
30 : :
31 : : /*
32 : : * Es werden Pointer auf Objekte verwaltet. Diese werden in einem einfachen
33 : : * PtrArray verwaltet.
34 : : * Angelegt (new) werden die Objekte von Cache-Zugriffsklassen, zuerstoert
35 : : * werden die Objekte vom Cache.
36 : : *
37 : : * Auf die Objekte kann wahlweise per Index in das Array oder per Suche
38 : : * zugegriffen werden. Soll per Index zugegriffen werden, so obliegt die
39 : : * Verwaltung des Index dem Anwender des Cache.
40 : : *
41 : : * Fuer die verwalteten Cache-Objekte gibt es eine Basisklasse, von dieser
42 : : * sind spezifische Klassen abzuleiten.
43 : : * In der Basisklasse werden die Cache-Objekte eines Cache doppelt verkettet,
44 : : * das ermoeglich die Implementierung eines LRU-Algorithmus.
45 : : *
46 : : * Der LRU kann in der Cache-Basisklasse manipuliert werden, indem ein
47 : : * virtueller First-Pointer gesetzt wird. Dieser kann auf den echten ersten
48 : : * plus einem Ofst gesetzt werden. Dadurch kann man den Anfangsbereich des
49 : : * Cache sichern und so dafuer sorgen, dass man waehrend bestimmter
50 : : * Operationen nicht den Cache versaut. Beispiel: Der Idle-Handler sollte nicht
51 : : * den Cache fuer den sichtbaren Bereich vernichten.
52 : : *
53 : : * Der Cache kann in der Groesse erweitert und wieder verkleinert werden.
54 : : * Beispiel: Fuer jede neue Shell wird der Cache fuer FormatInfo vergrossert
55 : : * und beim Destruieren der Shell wieder verkleinert.
56 : : *
57 : : */
58 : :
59 : : #include <vector>
60 : :
61 : : #include <rtl/ustring.hxx>
62 : :
63 : : class SwCacheObj;
64 : :
65 : : typedef std::vector<SwCacheObj*> SwCacheObjArr;
66 : : class SwCache
67 : : {
68 : : SwCacheObjArr m_aCacheObjects;
69 : : std::vector<sal_uInt16> aFreePositions; //Freie Positionen fuer das Insert wenn
70 : : //die Maximalgrenze nicht erreicht ist.
71 : : //Immer wenn ein Objekt ausgetragen wird,
72 : : //so wird seine Position hier eingetragen.
73 : :
74 : : SwCacheObj *pRealFirst; //_immer_ der echte LRU-erste
75 : : SwCacheObj *pFirst; //der virtuelle erste.
76 : : SwCacheObj *pLast;
77 : :
78 : : const sal_uInt16 nMax; //Mehr sollen nicht aufgenommen werden,
79 : : //der Cache kann aber dynamisch um jeweils
80 : : //nMax vergroessert werden.
81 : : sal_uInt16 nCurMax; //Mehr werden nicht aufgenommen.
82 : :
83 : :
84 : : void DeleteObj( SwCacheObj *pObj );
85 : :
86 : : #ifdef DBG_UTIL
87 : : rtl::OString m_aName;
88 : : long m_nAppend; /// number of entries appended
89 : : long m_nInsertFree; /// number of entries inserted on freed position
90 : : long m_nReplace; /// number of LRU replacements
91 : : long m_nGetSuccess;
92 : : long m_nGetFail;
93 : : long m_nToTop; /// number of reordering (LRU)
94 : : long m_nDelete; /// number of explicit deletes
95 : : long m_nGetSeek; /// number of gets without index
96 : : long m_nAverageSeekCnt; /// number of seeks for all gets without index
97 : : long m_nFlushCnt; /// number of flush calls
98 : : long m_nFlushedObjects;
99 : : long m_nIncreaseMax; /// number of cache size increases
100 : : long m_nDecreaseMax; /// number of cache size decreases
101 : :
102 : : void Check();
103 : : #endif
104 : :
105 : : public:
106 : :
107 : : //nur sal_uInt8 hineinstecken!!!
108 : : #ifdef DBG_UTIL
109 : : SwCache( const sal_uInt16 nInitSize, const rtl::OString &rNm );
110 : : #else
111 : : SwCache( const sal_uInt16 nInitSize );
112 : : #endif
113 : : // the destructor will free all objects still in the vector
114 : : ~SwCache();
115 : :
116 : : void Flush( const sal_uInt8 nPercent = 100 );
117 : :
118 : : //bToTop == sal_False -> Keine LRU-Umsortierung!
119 : : SwCacheObj *Get( const void *pOwner, const sal_Bool bToTop = sal_True );
120 : : SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex,
121 : : const sal_Bool bToTop = sal_True );
122 : : void ToTop( SwCacheObj *pObj );
123 : :
124 : : sal_Bool Insert( SwCacheObj *pNew );
125 : : void Delete( const void *pOwner );
126 : : // void Delete( const void *pOwner, const sal_uInt16 nIndex );
127 : :
128 : : void SetLRUOfst( const sal_uInt16 nOfst ); //nOfst sagt wieviele unangetastet
129 : : //bleiben sollen.
130 : 4638 : void ResetLRUOfst() { pFirst = pRealFirst; }
131 : :
132 : : inline void IncreaseMax( const sal_uInt16 nAdd );
133 : : inline void DecreaseMax( const sal_uInt16 nSub );
134 : 7225 : sal_uInt16 GetCurMax() const { return nCurMax; }
135 : 21127 : inline SwCacheObj *First() { return pRealFirst; }
136 : : inline SwCacheObj *Last() { return pLast; }
137 : : inline SwCacheObj *Next( SwCacheObj *pCacheObj);
138 : : inline SwCacheObj* operator[](sal_uInt16 nIndex) { return m_aCacheObjects[nIndex]; }
139 : : inline sal_uInt16 size() { return m_aCacheObjects.size(); }
140 : : };
141 : :
142 : : //Cache-Manipulation auf die sichere Art.
143 : : class SwSaveSetLRUOfst
144 : : {
145 : : SwCache &rCache;
146 : : public:
147 : 4638 : SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
148 : 4638 : : rCache( rC ) { rCache.SetLRUOfst( nOfst ); }
149 : :
150 : 4638 : ~SwSaveSetLRUOfst() { rCache.ResetLRUOfst(); }
151 : : };
152 : :
153 : : //Das allgemeine CacheObjekt. Anwender des Cache muessen eine Klasse vom
154 : : //CacheObjekt ableiten und dort die Nutzdaten unterbringen.
155 : :
156 : : class SwCacheObj
157 : : {
158 : : friend class SwCache; //Der darf alles
159 : :
160 : : SwCacheObj *pNext; //Fuer die LRU-Verkettung.
161 : : SwCacheObj *pPrev;
162 : :
163 : : sal_uInt16 nCachePos; //Position im Cache-Array.
164 : :
165 : : sal_uInt8 nLock;
166 : :
167 : 1936433 : inline SwCacheObj *GetNext() { return pNext; }
168 : 374625 : inline SwCacheObj *GetPrev() { return pPrev; }
169 : 274554 : inline void SetNext( SwCacheObj *pNew ) { pNext = pNew; }
170 : 370029 : inline void SetPrev( SwCacheObj *pNew ) { pPrev = pNew; }
171 : :
172 : 26008 : inline void SetCachePos( const sal_uInt16 nNew ) { nCachePos = nNew; }
173 : :
174 : : protected:
175 : : const void *pOwner;
176 : : inline void SetOwner( const void *pNew ) { pOwner = pNew; }
177 : :
178 : : public:
179 : :
180 : : SwCacheObj( const void *pOwner );
181 : : virtual ~SwCacheObj();
182 : :
183 : 102269 : inline const void *GetOwner() const { return pOwner; }
184 : : inline sal_Bool IsOwner( const void *pNew ) const;
185 : :
186 : 64932 : inline sal_uInt16 GetCachePos() const { return nCachePos; }
187 : : inline void Invalidate() { pOwner = 0; }
188 : :
189 : 16727 : inline sal_Bool IsLocked() const { return 0 != nLock; }
190 : :
191 : : #ifdef DBG_UTIL
192 : : void Lock();
193 : : void Unlock();
194 : : #else
195 : 1197597 : inline void Lock() { ++nLock; }
196 : 1197507 : inline void Unlock() { --nLock; }
197 : : #endif
198 : :
199 : : SwCacheObj *Next() { return pNext; }
200 : : SwCacheObj *Prev() { return pPrev; }
201 : :
202 : : };
203 : :
204 : : //Zugriffsklasse fuer den Cache. Im CTor wird das CacheObjekt erzeugt.
205 : : //Wenn der Cache keines herausrueckt wird der Member zunaechst auf 0 gesetzt.
206 : : //Beim Get wird dann eines erzeugt und, falls moeglich, in den Cache
207 : : //eingetragen.
208 : : //Anwender der des Cache muessen eine Klasse vom Access ableiten um
209 : : //fuer Typsicherheit zu sorgen, die Basisklasse sollte fuer das Get aber immer
210 : : //gerufen werden, ein Abgeleitetes Get sollte nur der Typsicherheit dienen.
211 : : //Cache-Objekte werden stets gelockt solange die Instanz lebt.
212 : :
213 : : class SwCacheAccess
214 : : {
215 : : SwCache &rCache;
216 : :
217 : : void _Get();
218 : :
219 : : protected:
220 : : SwCacheObj *pObj;
221 : : const void *pOwner; //Kann ggf. in NewObj benutzt werden.
222 : :
223 : : virtual SwCacheObj *NewObj() = 0;
224 : :
225 : : inline SwCacheObj *Get();
226 : :
227 : : inline SwCacheAccess( SwCache &rCache, const void *pOwner, sal_Bool bSeek = sal_True );
228 : : inline SwCacheAccess( SwCache &rCache, const void *pOwner, const sal_uInt16 nIndex );
229 : :
230 : : public:
231 : : virtual ~SwCacheAccess();
232 : :
233 : : virtual sal_Bool IsAvailable() const;
234 : :
235 : : //Abkuerzung fuer diejenigen, die wissen, das die Ableitung das IsAvailable
236 : : //nicht ueberladen haben.
237 : 547177 : sal_Bool IsAvail() const { return pObj != 0; }
238 : : };
239 : :
240 : 1325 : inline void SwCache::IncreaseMax( const sal_uInt16 nAdd )
241 : : {
242 : 1325 : nCurMax = nCurMax + sal::static_int_cast< sal_uInt16 >(nAdd);
243 : : #ifdef DBG_UTIL
244 : : ++m_nIncreaseMax;
245 : : #endif
246 : 1325 : }
247 : 1250 : inline void SwCache::DecreaseMax( const sal_uInt16 nSub )
248 : : {
249 [ + - ]: 1250 : if ( nCurMax > nSub )
250 : 1250 : nCurMax = nCurMax - sal::static_int_cast< sal_uInt16 >(nSub);
251 : : #ifdef DBG_UTIL
252 : : ++m_nDecreaseMax;
253 : : #endif
254 : 1250 : }
255 : :
256 : 2180547 : inline sal_Bool SwCacheObj::IsOwner( const void *pNew ) const
257 : : {
258 [ + - ][ + + ]: 2180547 : return pOwner && pOwner == pNew;
259 : : }
260 : :
261 : 25966 : inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
262 : : {
263 [ + - ]: 25966 : if ( pCacheObj )
264 : 25966 : return pCacheObj->GetNext();
265 : : else
266 : 25966 : return NULL;
267 : : }
268 : :
269 : 259722 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, sal_Bool bSeek ) :
270 : : rCache( rC ),
271 : : pObj( 0 ),
272 : 259722 : pOwner( pOwn )
273 : : {
274 [ + + ][ + - ]: 259722 : if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
[ + + ][ + + ]
275 : 244296 : pObj->Lock();
276 : 259722 : }
277 : :
278 : 583276 : inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
279 : : const sal_uInt16 nIndex ) :
280 : : rCache( rC ),
281 : : pObj( 0 ),
282 : 583276 : pOwner( pOwn )
283 : : {
284 [ + + ][ + + ]: 583276 : if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
[ + + ]
285 : 561592 : pObj->Lock();
286 : 583276 : }
287 : :
288 : 1203938 : inline SwCacheObj *SwCacheAccess::Get()
289 : : {
290 [ + + ]: 1203938 : if ( !pObj )
291 : 21094 : _Get();
292 : 1203938 : return pObj;
293 : : }
294 : :
295 : :
296 : : #endif
297 : :
298 : : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
|