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