summaryrefslogtreecommitdiff
path: root/sw/source/core/inc/swcache.hxx
blob: c225e1d47d839a3efdcbdf2b600b0fd51f4b9726 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
/*************************************************************************
 *
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * Copyright 2008 by Sun Microsystems, Inc.
 *
 * OpenOffice.org - a multi-platform office productivity suite
 *
 * $RCSfile: swcache.hxx,v $
 * $Revision: 1.6 $
 *
 * This file is part of OpenOffice.org.
 *
 * OpenOffice.org is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * OpenOffice.org is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details
 * (a copy is included in the LICENSE file that accompanied this code).
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with OpenOffice.org.  If not, see
 * <http://www.openoffice.org/license.html>
 * for a copy of the LGPLv3 License.
 *
 ************************************************************************/
#ifndef _SWCACHE_HXX
#define _SWCACHE_HXX



/*
 * Es werden Pointer auf Objekte verwaltet. Diese werden in einem einfachen
 * PtrArray verwaltet.
 * Angelegt (new) werden die Objekte von Cache-Zugriffsklassen, zuerstoert
 * werden die Objekte vom Cache.
 *
 * Auf die Objekte kann wahlweise per Index in das Array oder per Suche
 * zugegriffen werden. Soll per Index zugegriffen werden, so obliegt die
 * Verwaltung des Index dem Anwender des Cache.
 *
 * Fuer die verwalteten Cache-Objekte gibt es eine Basisklasse, von dieser
 * sind spezifische Klassen abzuleiten.
 * In der Basisklasse werden die Cache-Objekte eines Cache doppelt verkettet,
 * das ermoeglich die Implementierung eines LRU-Algorithmus.
 *
 * Der LRU kann in der Cache-Basisklasse manipuliert werden, indem ein
 * virtueller First-Pointer gesetzt wird. Dieser kann auf den echten ersten
 * plus einem Ofst gesetzt werden. Dadurch kann man den Anfangsbereich des
 * Cache sichern und so dafuer sorgen, dass man waehrend bestimmter
 * Operationen nicht den Cache versaut. Beispiel: Der Idle-Handler sollte nicht
 * den Cache fuer den sichtbaren Bereich vernichten.
 *
 * Der Cache kann in der Groesse erweitert und wieder verkleinert werden.
 * Beispiel: Fuer jede neue Shell wird der Cache fuer FormatInfo vergrossert
 * und beim Destruieren der Shell wieder verkleinert.
 *
 */

#ifdef DBG_UTIL
#ifndef _STRING_HXX //autogen
#include <tools/string.hxx>
#endif
#endif

#ifndef _SVSTDARR_HXX
#define _SVSTDARR_USHORTS
#include <svl/svstdarr.hxx>
#endif

class SwCacheObj;

SV_DECL_PTRARR_DEL(SwCacheObjArr,SwCacheObj*,1,1)

class SwCache : public SwCacheObjArr
{
    SvUShorts aFreePositions;       //Freie Positionen fuer das Insert wenn
                                    //die Maximalgrenze nicht erreicht ist.
                                    //Immer wenn ein Objekt ausgetragen wird,
                                    //so wird seine Position hier eingetragen.

    SwCacheObj *pRealFirst;         //_immer_ der echte LRU-erste
    SwCacheObj *pFirst;             //der virtuelle erste.
    SwCacheObj *pLast;

    const USHORT nMax;              //Mehr sollen nicht aufgenommen werden,
                                    //der Cache kann aber dynamisch um jeweils
                                    //nMax vergroessert werden.
          USHORT nCurMax;           //Mehr werden nicht aufgenommen.


    void DeleteObj( SwCacheObj *pObj );

#ifdef DBG_UTIL
    ByteString aName;
    long nAppend;           //Anzahl der Eintragungen durch Erweiterung.
    long nInsertFree;       //Anzahl der Eintragungen auf freie Plaetze.
    long nReplace;          //Anzahl der Ersetzungen durch ein neues Objekt
    long nGetSuccess;       //Anzahl der Erfolgreichen Get's
    long nGetFail;          //Anzahl der nicht Erfolgreichen Get's
    long nToTop;            //Anzahl der Umsortierungen (LRU)
    long nDelete;           //Anzahl der Loeschungen (von Aussen)
    long nGetSeek;          //Anzahl der Get's ohne Index
    long nAverageSeekCnt;   //Anzahl der Seek's fuer alle Get's ohne Index
    long nFlushCnt;         //Anzahl von Flush-Aufrufen.
    long nFlushedObjects;   //Anzahl der wg. Flush vernichteten Objekte
    long nIncreaseMax;      //Anzahl Cache-Erweiterungen
    long nDecreaseMax;      //Anzahl Cache-Verkleinerungen

    void Check();           //Wird bei swcache.cxx mit DEBUG aktiv!
#endif

public:

    //nur BYTE hineinstecken!!!
#ifdef DBG_UTIL
    SwCache( const USHORT nInitSize, const USHORT nGrowSize,
            const ByteString &rNm );
    ~SwCache();
#else
    SwCache( const USHORT nInitSize, const USHORT nGrowSize );
#endif

    void Flush( const BYTE nPercent = 100 );

    //bToTop == FALSE -> Keine LRU-Umsortierung!
    SwCacheObj *Get( const void *pOwner, const BOOL bToTop = TRUE );
    SwCacheObj *Get( const void *pOwner, const USHORT nIndex,
                     const BOOL bToTop = TRUE );
    void ToTop( SwCacheObj *pObj );

    BOOL Insert( SwCacheObj *pNew );
    void Delete( const void *pOwner );
//  void Delete( const void *pOwner, const USHORT nIndex );

    void SetLRUOfst( const USHORT nOfst );      //nOfst sagt wieviele unangetastet
                                                //bleiben sollen.
    void ResetLRUOfst() { pFirst = pRealFirst; }

    inline void IncreaseMax( const USHORT nAdd );
    inline void DecreaseMax( const USHORT nSub );
    USHORT GetCurMax() const { return nCurMax; }
    inline SwCacheObj *First() { return pRealFirst; }
    inline SwCacheObj *Last()  { return pLast; }
    inline SwCacheObj *Next( SwCacheObj *pCacheObj);
};

//Cache-Manipulation auf die sichere Art.
class SwSaveSetLRUOfst
{
    SwCache &rCache;
public:
    SwSaveSetLRUOfst( SwCache &rC, const USHORT nOfst )
        : rCache( rC )          { rCache.SetLRUOfst( nOfst );  }

    ~SwSaveSetLRUOfst()         { rCache.ResetLRUOfst(); }
};

//Das allgemeine CacheObjekt. Anwender des Cache muessen eine Klasse vom
//CacheObjekt ableiten und dort die Nutzdaten unterbringen.

class SwCacheObj
{
    friend class SwCache;   //Der darf alles

    SwCacheObj *pNext;      //Fuer die LRU-Verkettung.
    SwCacheObj *pPrev;

    USHORT nCachePos;       //Position im Cache-Array.

    BYTE        nLock;

    inline SwCacheObj *GetNext() { return pNext; }
    inline SwCacheObj *GetPrev() { return pPrev; }
    inline void SetNext( SwCacheObj *pNew )  { pNext = pNew; }
    inline void SetPrev( SwCacheObj *pNew )  { pPrev = pNew; }

    inline void   SetCachePos( const USHORT nNew ) { nCachePos = nNew; }

protected:
    const void *pOwner;
    inline void SetOwner( const void *pNew ) { pOwner = pNew; }

public:

    SwCacheObj( const void *pOwner );
    virtual ~SwCacheObj();

    inline const void *GetOwner() const { return pOwner; }
    inline BOOL IsOwner( const void *pNew ) const;

    inline USHORT GetCachePos() const { return nCachePos; }
    inline void Invalidate()          { pOwner = 0; }

    inline BOOL IsLocked() const { return 0 != nLock; }

#ifndef DBG_UTIL
    inline void Lock() { ++nLock; }
    inline void Unlock() { --nLock; }
#else
    void Lock();
    void Unlock();
#endif

    SwCacheObj *Next() { return pNext; }
    SwCacheObj *Prev() { return pPrev; }

};

//Zugriffsklasse fuer den Cache. Im CTor wird das CacheObjekt erzeugt.
//Wenn der Cache keines herausrueckt wird der Member zunaechst auf 0 gesetzt.
//Beim Get wird dann eines erzeugt und, falls moeglich, in den Cache
//eingetragen.
//Anwender der des Cache muessen eine Klasse vom Access ableiten um
//fuer Typsicherheit zu sorgen, die Basisklasse sollte fuer das Get aber immer
//gerufen werden, ein Abgeleitetes Get sollte nur der Typsicherheit dienen.
//Cache-Objekte werden stets gelockt solange die Instanz lebt.

class SwCacheAccess
{
    SwCache &rCache;

    void _Get();

protected:
    SwCacheObj *pObj;
    const void *pOwner;     //Kann ggf. in NewObj benutzt werden.

    virtual SwCacheObj *NewObj() = 0;

    inline SwCacheObj *Get();

    inline SwCacheAccess( SwCache &rCache, const void *pOwner, BOOL bSeek = TRUE );
    inline SwCacheAccess( SwCache &rCache, const void *pOwner, const USHORT nIndex );

public:
    virtual ~SwCacheAccess();

    virtual BOOL IsAvailable() const;

    //Abkuerzung fuer diejenigen, die wissen, das die Ableitung das IsAvailable
    //nicht ueberladen haben.
    BOOL IsAvail() const { return pObj != 0; }
};

inline void SwCache::IncreaseMax( const USHORT nAdd )
{
    nCurMax = nCurMax + sal::static_int_cast< USHORT >(nAdd);
#ifdef DBG_UTIL
    ++nIncreaseMax;
#endif
}
inline void SwCache::DecreaseMax( const USHORT nSub )
{
    if ( nCurMax > nSub )
        nCurMax = nCurMax - sal::static_int_cast< USHORT >(nSub);
#ifdef DBG_UTIL
    ++nDecreaseMax;
#endif
}

inline BOOL SwCacheObj::IsOwner( const void *pNew ) const
{
    return pOwner && pOwner == pNew;
}

inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj)
{
    if ( pCacheObj )
        return pCacheObj->GetNext();
    else
        return NULL;
}

inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, BOOL bSeek ) :
    rCache( rC ),
    pObj( 0 ),
    pOwner( pOwn )
{
    if ( bSeek && pOwner && 0 != (pObj = rCache.Get( pOwner )) )
        pObj->Lock();
}

inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn,
                              const USHORT nIndex ) :
    rCache( rC ),
    pObj( 0 ),
    pOwner( pOwn )
{
    if ( pOwner && 0 != (pObj = rCache.Get( pOwner, nIndex )) )
        pObj->Lock();
}

inline SwCacheObj *SwCacheAccess::Get()
{
    if ( !pObj )
        _Get();
    return pObj;
}


#endif