Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   Related Pages  

Cache.h

00001 /*
00002  * Cache
00003  *
00004  * Copyright (C) 2001 Barnaby Gray <barnaby@beedesign.co.uk>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2.1 of the License, or (at your option) any later version.
00010  *
00011  * This library is distributed in the hope that it will be useful,
00012  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
00019  *
00020  */
00021 
00022 #ifndef CACHE_H
00023 #define CACHE_H
00024 
00025 #include <list>
00026 #include <time.h>
00027 
00028 namespace ICQ2000 {
00029   
00030   /*
00031    * This class will cache an id to an object, it's templated
00032    * since it'll be useful in several places with different sorts of
00033    * ids and objects.
00034    */
00035   
00036   template <typename Key, typename Value> class CacheItem {
00037    protected:
00038     unsigned int m_timeout;
00039     time_t m_timestamp;
00040     Key m_key;
00041     Value m_value;
00042 
00043    public:
00044     CacheItem(const Key &k, const Value &v, unsigned int timeout);
00045     
00046     const Key& getKey() const;
00047     Value& getValue();
00048     time_t getTimestamp() const;
00049     time_t getExpiryTime() const;
00050     void setTimestamp(time_t t);
00051     void setTimeout(time_t t);
00052     void refresh();
00053   };
00054 
00055   template < typename Key, typename Value >
00056   class Cache {
00057    protected:
00058     typedef typename std::list< CacheItem<Key,Value> >::iterator literator;
00059     typedef typename std::list< CacheItem<Key,Value> >::const_iterator citerator;
00060 
00061     unsigned int m_timeout;
00062     
00063     /*
00064      * list for storing them in order to timeout
00065      * a hash could be used as well, but efficiency isn't really an
00066      * issue - there shouldn't be more than 10 items in here at any one point
00067      */
00068     std::list< CacheItem<Key,Value> > m_list;
00069 
00070     citerator lookup(const Key& k) const {
00071       citerator curr = m_list.begin();
00072       while (curr != m_list.end()) {
00073         if ((*curr).getKey() == k) return curr;
00074         ++curr;
00075       }
00076       return m_list.end();
00077     }
00078     
00079     literator lookup(const Key& k) {
00080       literator curr = m_list.begin();
00081       while (curr != m_list.end()) {
00082         if ((*curr).getKey() == k) return curr;
00083         ++curr;
00084       }
00085       return m_list.end();
00086     }
00087     
00088    public:
00089     Cache();
00090     virtual ~Cache();
00091 
00092     bool exists(const Key &k) const {
00093       citerator i = lookup(k);
00094       return (i != m_list.end());
00095     }
00096 
00097     Value& operator[](const Key &k) {
00098       literator i = lookup(k);
00099       if (i == m_list.end()) {
00100         return insert(k, Value());
00101       } else {
00102         return (*i).getValue();
00103       }
00104     }
00105 
00106     void remove(const Key &k)  {
00107       literator i = lookup(k);
00108       if (i != m_list.end()) removeItem(i);
00109     }
00110 
00111     virtual void removeItem(const literator& l) {
00112       m_list.erase(l);
00113     }
00114 
00115     virtual void expireItem(const literator& l) {
00116       // might want to override to add signalling on expiring of items
00117       removeItem(l);
00118     }
00119     
00120     void expireAll() {
00121       while (!m_list.empty()) {
00122         expireItem(m_list.begin());
00123       }
00124     }
00125 
00126     void removeAll() {
00127       while (!m_list.empty()) {
00128         removeItem(m_list.begin());
00129       }
00130     }
00131 
00132     Value& insert(const Key &k, const Value &v) {
00133       CacheItem<Key,Value> t(k,v,m_timeout);
00134       return (*insert(t)).getValue();
00135     }
00136 
00137     literator insert(const CacheItem<Key,Value>& t) {
00138       time_t exp_time = t.getExpiryTime();
00139 
00140       literator l = m_list.end();
00141       while (l != m_list.begin()) {
00142         --l;
00143         if ( (*l).getExpiryTime() < exp_time ) {
00144           ++l;
00145           break;
00146         }
00147       }
00148       return m_list.insert(l, t);
00149     }
00150 
00151     bool empty() const {
00152       return m_list.empty();
00153     }
00154 
00155     const Key& front() const {
00156       return m_list.front().getKey();
00157     }
00158 
00159     void refresh(const Key &k) {
00160       literator i = lookup(k);
00161       if (i != m_list.end()) {
00162         CacheItem<Key,Value> t(*i);
00163         m_list.erase(i);
00164         insert(t);
00165       }
00166     }
00167 
00168     unsigned int getDefaultTimeout() { return m_timeout; }
00169     void setDefaultTimeout(unsigned int s) { m_timeout = s; }
00170 
00171     void setTimeout(const Key &k, unsigned int s) {
00172       literator i = lookup(k);
00173       if (i != m_list.end()) {
00174         CacheItem<Key,Value> t(*i);
00175         t.setTimeout(s);
00176         m_list.erase(i);
00177         insert(t);
00178       }
00179     }
00180 
00181     void clearoutPoll() {
00182       time_t n = time(NULL);
00183       while (!m_list.empty() && m_list.front().getExpiryTime() < n)
00184         expireItem( m_list.begin() );
00185     }
00186 
00187   };
00188 
00189   template <typename Key, typename Value>
00190   CacheItem<Key,Value>::CacheItem(const Key &k, const Value &v, unsigned int timeout)
00191     : m_timeout(timeout), m_timestamp(time(NULL)), 
00192       m_key(k), m_value(v) { }
00193 
00194   template <typename Key, typename Value>
00195   void CacheItem<Key,Value>::setTimestamp(time_t t) { m_timestamp = t; }
00196   
00197   template <typename Key, typename Value>
00198   void CacheItem<Key,Value>::setTimeout(time_t t) { m_timeout = t; }
00199   
00200   template <typename Key, typename Value>
00201   time_t CacheItem<Key,Value>::getTimestamp() const { return m_timestamp; }
00202   
00203   template <typename Key, typename Value>
00204   time_t CacheItem<Key,Value>::getExpiryTime() const { return m_timestamp + m_timeout; }
00205   
00206   template <typename Key, typename Value>
00207   void CacheItem<Key,Value>::refresh() { m_timestamp = time(NULL); }
00208   
00209   template <typename Key, typename Value>
00210   const Key& CacheItem<Key,Value>::getKey() const {
00211     return m_key;
00212   }
00213 
00214   template <typename Key, typename Value>
00215   Value& CacheItem<Key,Value>::getValue() {
00216     return m_value;
00217   }
00218 
00219   template <typename Key, typename Value>
00220   Cache<Key,Value>::Cache() {
00221     setDefaultTimeout(60); // default timeout
00222   }
00223 
00224   template <typename Key, typename Value>
00225   Cache<Key,Value>::~Cache() {
00226     removeAll();
00227   }
00228  
00229 }
00230 
00231 #endif

Generated on Sun Jul 21 10:57:32 2002 for libicq2000 by doxygen1.2.16