GenericCache.h

Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2005 Palmsource, Inc.
00003  * 
00004  * This software is licensed as described in the file LICENSE, which
00005  * you should have received as part of this distribution. The terms
00006  * are also available at http://www.openbinder.org/license.html.
00007  * 
00008  * This software consists of voluntary contributions made by many
00009  * individuals. For the exact contribution history, see the revision
00010  * history and logs, available at http://www.openbinder.org
00011  */
00012 
00013 #ifndef SUPPORT_GENERIC_CACHE_H
00014 #define SUPPORT_GENERIC_CACHE_H
00015 
00021 #include <PalmTypes.h>
00022 #include <support/Atom.h>
00023 #include <support/Locker.h>
00024 #include <support/KeyedVector.h>
00025 #include <support/StdIO.h>
00026 #if _SUPPORTS_RTTI
00027 #include <typeinfo>
00028 #endif
00029 
00030 #if _SUPPORTS_NAMESPACE
00031 namespace palmos {
00032 namespace support {
00033 #endif
00034 
00039 class ITextOutput;
00040 
00041 /*****************************************************************************/
00042 
00043 enum {
00044     B_GENERIC_CACHE_SIZE_UNLIMITED = 0          
00045 };
00046 
00047 enum {
00048     B_GENERIC_CACHE_NEVER_PURGE = 0x00000001,   
00049     B_GENERIC_CACHE_DONT_ADD    = 0x00000002,   
00050     B_GENERIC_CACHE_DONT_PURGE  = 0x00000004    
00051 };
00052 
00053 class SAbstractCache
00054 {
00055 public:
00056     const void*     AbstractLookup(const void *key, int32_t flags) const;
00057     status_t        AbstractAdd(const void *key, const void *data, int32_t flags);
00058     status_t        AbstractRemove(const void *key);
00059     void            Dump(const sptr<ITextOutput>& io) const;
00060 protected:
00061                     SAbstractCache(ssize_t cacheSize);
00062     virtual         ~SAbstractCache();
00063 private:
00064     virtual void                            PerformPrintItem(const void* data, const sptr<ITextOutput>& io) const = 0;
00065     virtual ssize_t                         PerformSize(const void* data) const = 0;
00066     virtual uint32_t&                       PerformEntryAge(const void* entry) const = 0;
00067     virtual const void*                     PerformEntryData(const void* entry) const = 0;
00068     virtual const SAbstractKeyedVector&     Entries() const = 0;
00069     virtual SAbstractKeyedVector&           Entries() = 0;
00070     virtual status_t                        CreateEntry(const void* key, const void* data, uint32_t age) = 0;
00071     inline uint32_t tick() const;
00072     inline ssize_t size_left() const { return m_cacheSize-m_sizeUsed; }
00073     mutable uint32_t    m_age;
00074     ssize_t             m_cacheSize;
00075     ssize_t             m_sizeUsed;
00076 };
00077 
00078 /*****************************************************************************/
00079 
00080 template<class KEY, class TYPE>
00081 class SGenericCache : private SAbstractCache
00082 {
00083 public:
00084     inline                      SGenericCache(ssize_t cacheSize);
00085     virtual inline              ~SGenericCache();
00086 
00087     inline  TYPE                Lookup(const KEY& key, int32_t flags = 0) const;
00088     inline  status_t            Add(const KEY& key, const TYPE& data, int32_t flags = 0);
00089     inline  status_t            Remove(const KEY& key);
00090     inline void                 Dump(const sptr<ITextOutput>& io) const;
00091 
00092 private:
00093     virtual void                            PerformPrintItem(const void* data, const sptr<ITextOutput>& io) const;
00094     virtual ssize_t                         PerformSize(const void* data) const;
00095     virtual uint32_t&                       PerformEntryAge(const void* entry) const;
00096     virtual const void*                     PerformEntryData(const void* entry) const;
00097     virtual const SAbstractKeyedVector&     Entries() const;
00098     virtual SAbstractKeyedVector&           Entries();
00099     virtual status_t                        CreateEntry(const void* key, const void* data, uint32_t age);
00100     template<class ENTTYPE> struct entry_t {
00101         mutable uint32_t    age;    // if 0xFFFFFFFF, value cannot be expunged
00102         ENTTYPE             data;
00103         entry_t() {}
00104         entry_t(const entry_t& from)
00105             :   age(from.age),
00106                 data(from.data)
00107         {}
00108     };
00109     SKeyedVector<KEY, entry_t<TYPE> >       m_entries;
00110     mutable SLocker m_lock;
00111 };
00112 
00115 /*-------------------------------------------------------------*/
00116 /*---- No user serviceable parts after this -------------------*/
00117 
00118 template<class TYPE> inline
00119 ssize_t PGenericCacheSize(const TYPE& data)
00120 {
00121     return data->Size();
00122 }
00123 
00124 
00125 template<class TYPE> inline
00126 const sptr<ITextOutput>& PGenericCachePrintItem(const sptr<ITextOutput>& io, const TYPE& data)
00127 {
00128 #if _SUPPORTS_RTTI
00129     io << &data << " (" << typeid(data).name() << ") size=" << PGenericCacheSize(data);
00130 #else
00131     io << &data << " size=" << PGenericCacheSize(data);
00132 #endif
00133     return io;
00134 }
00135 
00136 // ---------------------------------------------------------------------
00137 
00138 template<class KEY, class TYPE> inline
00139 SGenericCache<KEY, TYPE>::SGenericCache(ssize_t cacheSize)
00140     : SAbstractCache(cacheSize), m_lock("SGenericCache::m_lock")
00141 {
00142 }
00143 
00144 template<class KEY, class TYPE> inline
00145 SGenericCache<KEY, TYPE>::~SGenericCache()
00146 {
00147 }
00148 
00149 // ---------------------------------------------------------------------
00150 
00151 template<class KEY, class TYPE> inline
00152 void SGenericCache<KEY, TYPE>::Dump(const sptr<ITextOutput>& io) const
00153 {
00154     SLocker::Autolock _l(m_lock);
00155     SAbstractCache::Dump(io);
00156 }
00157 
00158 template<class KEY, class TYPE> inline
00159 TYPE SGenericCache<KEY, TYPE>::Lookup(const KEY& key, int32_t flags) const
00160 {
00161     SLocker::Autolock _l(m_lock);
00162     return *(static_cast< const TYPE* >( AbstractLookup(&key, flags) ));
00163 }
00164 
00165 template<class KEY, class TYPE> inline
00166 status_t SGenericCache<KEY, TYPE>::Add(const KEY& key, const TYPE& data, int32_t flags)
00167 {
00168     SLocker::Autolock _l(m_lock);
00169     return AbstractAdd(&key, &data, flags);
00170 }
00171 
00172 template<class KEY, class TYPE> inline
00173 status_t SGenericCache<KEY, TYPE>::Remove(const KEY& key)
00174 {
00175     SLocker::Autolock _l(m_lock);
00176     return AbstractRemove(&key);
00177 }
00178 
00179 // ---------------------------------------------------------------------
00180 
00181 template<class KEY, class TYPE> inline
00182 void SGenericCache<KEY, TYPE>::PerformPrintItem(const void* data, const sptr<ITextOutput>& io) const
00183 {
00184     PGenericCachePrintItem(io, *static_cast< const TYPE* >(data));
00185 }
00186 
00187 template<class KEY, class TYPE> inline
00188 ssize_t SGenericCache<KEY, TYPE>::PerformSize(const void *data) const
00189 {
00190     return PGenericCacheSize(*static_cast< const TYPE* >(data));
00191 }
00192 
00193 template<class KEY, class TYPE> inline
00194 uint32_t& SGenericCache<KEY, TYPE>::PerformEntryAge(const void* entry) const
00195 {
00196     return static_cast<const entry_t<TYPE>*>(entry)->age;
00197 }
00198 
00199 template<class KEY, class TYPE> inline
00200 const void* SGenericCache<KEY, TYPE>::PerformEntryData(const void* entry) const
00201 {
00202     return &(static_cast<const entry_t<TYPE>*>(entry)->data);
00203 }
00204 
00205 // ---------------------------------------------------------------------
00206 
00207 template<class KEY, class TYPE> inline
00208 const SAbstractKeyedVector& SGenericCache<KEY, TYPE>::Entries() const
00209 {
00210     return *(static_cast<const SAbstractKeyedVector*>((const void*)&m_entries));
00211 }
00212 
00213 template<class KEY, class TYPE> inline
00214 SAbstractKeyedVector& SGenericCache<KEY, TYPE>::Entries()
00215 {
00216     return *(static_cast<SAbstractKeyedVector*>((void*)&m_entries));
00217 }
00218 
00219 template<class KEY, class TYPE> inline
00220 status_t SGenericCache<KEY, TYPE>::CreateEntry(const void* key, const void* data, uint32_t age)
00221 {
00222     entry_t<TYPE> entry;
00223     entry.age = age;
00224     entry.data = *(static_cast< const TYPE* >(data));
00225     return m_entries.AddItem(*(static_cast<const KEY*>(key)), entry);
00226 }
00227 
00228 /*****************************************************************************/
00229 
00230 #if _SUPPORTS_NAMESPACE
00231 } } // namespace palmos::support
00232 #endif
00233 
00234 #endif