diff options
Diffstat (limited to 'sw/source/core/inc/swcache.hxx')
-rw-r--r-- | sw/source/core/inc/swcache.hxx | 265 |
1 files changed, 265 insertions, 0 deletions
diff --git a/sw/source/core/inc/swcache.hxx b/sw/source/core/inc/swcache.hxx new file mode 100644 index 000000000..92b678c07 --- /dev/null +++ b/sw/source/core/inc/swcache.hxx @@ -0,0 +1,265 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ +#ifndef INCLUDED_SW_SOURCE_CORE_INC_SWCACHE_HXX +#define INCLUDED_SW_SOURCE_CORE_INC_SWCACHE_HXX + +/** + * Here, we manage pointers in a simple PtrArray to objects. + * These objects are created (using new) in cache access classes; they are + * destroyed by the cache. + * + * One can access these objects by array index or by searching in the array. + * If you access it by index, managing the index is the responsibility of + * the cache user. + * + * The cached objects are derived from the base class SwCacheObj. + * In it, the cache objects are doubly-linked which allows for the use of + * an LRU algorithm. + * + * The LRU algorithm can be changed in the base class, by setting a virtual + * First Pointer. It can be set to the first real one plus an offset. + * By doing so we can protect the start area of the cache and make sure we + * don't mess up the cache during some special operations. + * E.g.: the Idle Handler should not destroy the cache for the visible area. + * + * The cache can be grown and shrunk in size. + * E.g.: The cache for FormatInfo is grown for every new Shell and shrunk + * when destroying them. + */ + +#include <memory> +#include <vector> + +#include <rtl/string.hxx> + +class SwCacheObj; + +class SwCache +{ + std::vector<std::unique_ptr<SwCacheObj>> m_aCacheObjects; + std::vector<sal_uInt16> m_aFreePositions; /// Free positions for the Insert if the maximum has not been reached + /// Every time an object is deregistered, its position is added here + SwCacheObj *m_pRealFirst; /// _ALWAYS_ the real first LRU + SwCacheObj *m_pFirst; /// The virtual first + SwCacheObj *m_pLast; + + sal_uInt16 m_nCurMax; // Maximum of accepted objects + + void DeleteObj( SwCacheObj *pObj ); + +#ifdef DBG_UTIL + OString m_aName; + long m_nAppend; /// number of entries appended + long m_nInsertFree; /// number of entries inserted on freed position + long m_nReplace; /// number of LRU replacements + long m_nGetSuccess; + long m_nGetFail; + long m_nToTop; /// number of reordering (LRU) + long m_nDelete; /// number of explicit deletes + long m_nGetSeek; /// number of gets without index + long m_nAverageSeekCnt; /// number of seeks for all gets without index + long m_nFlushCnt; /// number of flush calls + long m_nFlushedObjects; + long m_nIncreaseMax; /// number of cache size increases + long m_nDecreaseMax; /// number of cache size decreases + + void Check(); +#endif + +public: + +// Only add sal_uInt8!!! +#ifdef DBG_UTIL + SwCache( const sal_uInt16 nInitSize, const OString &rNm ); +#else + SwCache( const sal_uInt16 nInitSize ); +#endif + /// The dtor will free all objects still in the vector + ~SwCache(); + + void Flush(); + + //bToTop == false -> No LRU resorting! + SwCacheObj *Get( const void *pOwner, const bool bToTop = true ); + SwCacheObj *Get( const void *pOwner, const sal_uInt16 nIndex, + const bool bToTop = true ); + void ToTop( SwCacheObj *pObj ); + + bool Insert(SwCacheObj *pNew, bool isDuplicateOwnerAllowed); + void Delete(const void * pOwner, sal_uInt16 nIndex); + void Delete( const void *pOwner ); + + void SetLRUOfst( const sal_uInt16 nOfst ); /// nOfst determines how many are not to be touched + void ResetLRUOfst() { m_pFirst = m_pRealFirst; } + + void IncreaseMax( const sal_uInt16 nAdd ); + void DecreaseMax( const sal_uInt16 nSub ); + sal_uInt16 GetCurMax() const { return m_nCurMax; } + SwCacheObj *First() { return m_pRealFirst; } + static inline SwCacheObj *Next( SwCacheObj *pCacheObj); + SwCacheObj* operator[](sal_uInt16 nIndex) { return m_aCacheObjects[nIndex].get(); } + sal_uInt16 size() { return m_aCacheObjects.size(); } +}; + +/// Try to prevent visible SwParaPortions from being deleted. +class SwSaveSetLRUOfst +{ +public: + SwSaveSetLRUOfst(); + ~SwSaveSetLRUOfst(); +}; + +/** + * The Cache object base class + * Users of the Cache must derive a class from the SwCacheObj and store + * their payload there + */ +class SwCacheObj +{ + friend class SwCache; /// Can do everything + + SwCacheObj *m_pNext; /// For the LRU chaining + SwCacheObj *m_pPrev; + + sal_uInt16 m_nCachePos; /// Position in the Cache array + + sal_uInt8 m_nLock; + + SwCacheObj *GetNext() { return m_pNext; } + SwCacheObj *GetPrev() { return m_pPrev; } + void SetNext( SwCacheObj *pNew ) { m_pNext = pNew; } + void SetPrev( SwCacheObj *pNew ) { m_pPrev = pNew; } + + void SetCachePos(const sal_uInt16 nNew) + { + if (m_nCachePos != nNew) + { + m_nCachePos = nNew; + UpdateCachePos(); + } + } + virtual void UpdateCachePos() { } + +protected: + const void *m_pOwner; + +public: + + SwCacheObj( const void *pOwner ); + virtual ~SwCacheObj(); + + const void *GetOwner() const { return m_pOwner; } + inline bool IsOwner( const void *pNew ) const; + + sal_uInt16 GetCachePos() const { return m_nCachePos; } + + bool IsLocked() const { return 0 != m_nLock; } + +#ifdef DBG_UTIL + void Lock(); + void Unlock(); +#else + void Lock() { ++m_nLock; } + void Unlock() { --m_nLock; } +#endif +}; + +/** + * Access class for the Cache + * + * The Cache object is created in the ctor. + * If the Cache does not return one, the member is set to 0 and one is + * created on the Get() and added to the Cache (if possible). + * Cache users must derive a class from SwCacheAccess in order to + * guarantee type safety. The base class should always be called for the + * Get(). A derived Get() should only ever guarantee type safety. + * Cache objects are always locked for the instance's life time. + */ +class SwCacheAccess +{ + SwCache &m_rCache; + + void Get_(bool isDuplicateOwnerAllowed); + +protected: + SwCacheObj *m_pObj; + const void *m_pOwner; /// Can be use in NewObj + + virtual SwCacheObj *NewObj() = 0; + + inline SwCacheObj *Get(bool isDuplicateOwnerAllowed); + + inline SwCacheAccess( SwCache &rCache, const void *pOwner, bool bSeek ); + inline SwCacheAccess( SwCache &rCache, const void* nCacheId, const sal_uInt16 nIndex ); + +public: + virtual ~SwCacheAccess(); +}; + + +inline bool SwCacheObj::IsOwner( const void *pNew ) const +{ + return m_pOwner && m_pOwner == pNew; +} + +inline SwCacheObj *SwCache::Next( SwCacheObj *pCacheObj) +{ + if ( pCacheObj ) + return pCacheObj->GetNext(); + else + return nullptr; +} + +inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void *pOwn, bool bSeek ) : + m_rCache( rC ), + m_pObj( nullptr ), + m_pOwner( pOwn ) +{ + if ( bSeek && m_pOwner ) + { + m_pObj = m_rCache.Get( m_pOwner ); + if (m_pObj) + m_pObj->Lock(); + } +} + +inline SwCacheAccess::SwCacheAccess( SwCache &rC, const void* nCacheId, + const sal_uInt16 nIndex ) : + m_rCache( rC ), + m_pObj( nullptr ), + m_pOwner( nCacheId ) +{ + if ( m_pOwner ) + { + m_pObj = m_rCache.Get( m_pOwner, nIndex ); + if (m_pObj) + m_pObj->Lock(); + } +} + +inline SwCacheObj *SwCacheAccess::Get(bool const isDuplicateOwnerAllowed = true) +{ + if ( !m_pObj ) + Get_(isDuplicateOwnerAllowed); + return m_pObj; +} + +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |