00001 /******************************************************************************* 00002 * Copyright (C) 2003-2004 Vintela, Inc. All rights reserved. 00003 * 00004 * Redistribution and use in source and binary forms, with or without 00005 * modification, are permitted provided that the following conditions are met: 00006 * 00007 * - Redistributions of source code must retain the above copyright notice, 00008 * this list of conditions and the following disclaimer. 00009 * 00010 * - Redistributions in binary form must reproduce the above copyright notice, 00011 * this list of conditions and the following disclaimer in the documentation 00012 * and/or other materials provided with the distribution. 00013 * 00014 * - Neither the name of Vintela, Inc. nor the names of its 00015 * contributors may be used to endorse or promote products derived from this 00016 * software without specific prior written permission. 00017 * 00018 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 00019 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 00020 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 00021 * ARE DISCLAIMED. IN NO EVENT SHALL Vintela, Inc. OR THE CONTRIBUTORS 00022 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 00023 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 00024 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 00025 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 00026 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 00027 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 00028 * POSSIBILITY OF SUCH DAMAGE. 00029 *******************************************************************************/ 00030 00035 #ifndef OW_CACHE_INCLUDE_GUARD_HPP_ 00036 #define OW_CACHE_INCLUDE_GUARD_HPP_ 00037 #include "OW_config.h" 00038 #include "OW_HashMap.hpp" 00039 #include "OW_String.hpp" 00040 #include "OW_Mutex.hpp" 00041 #include "OW_MutexLock.hpp" 00042 #include "OW_CIMNULL.hpp" 00043 #include <list> 00044 00045 // The classes and functions defined in this file are not meant for general 00046 // use, they are internal implementation details. They may change at any time. 00047 00048 namespace OW_NAMESPACE 00049 { 00050 00052 template <typename T> 00053 class Cache 00054 { 00055 public: 00056 Cache(); 00057 00064 void addToCache(const T& cc, const String& key); 00065 00070 T getFromCache(const String& key); 00071 00077 void removeFromCache(const String& key); 00078 00081 void clearCache(); 00082 00086 void setMaxCacheSize(UInt32); 00087 00088 private: 00089 // a list of items that are cached. The list is sorted by lru. The least 00090 // recently acessed item will be at begin(), and the most recenly acessed 00091 // class will be at end()--; The second part of the pair is the key that 00092 // will be used in the index. 00093 // This is a list because we can quickly O(1) move items from the middle 00094 // to the end of the list when they're accessed. Also we need iterators 00095 // into the list to be stable. We can re-arrange items in the list 00096 // without having to update the HashMap index. 00097 typedef std::list<std::pair<T, String> > class_cache_t; 00098 00099 // the index into the cache. Speeds up finding an item when we need to. 00100 typedef HashMap<String, typename class_cache_t::iterator> cache_index_t; 00101 class_cache_t theCache; 00102 cache_index_t theCacheIndex; 00103 Mutex cacheGuard; 00104 UInt32 maxCacheSize; 00105 }; 00107 template <typename T> 00108 Cache<T>::Cache() 00109 : maxCacheSize(100) 00110 { 00111 } 00113 template <typename T> 00114 void 00115 Cache<T>::addToCache(const T& cc, const String& key) 00116 { 00117 MutexLock l(cacheGuard); 00118 if (theCacheIndex.size() >= maxCacheSize) 00119 { 00120 if (!theCache.empty()) 00121 { 00122 String key = theCache.begin()->second; 00123 theCache.pop_front(); 00124 theCacheIndex.erase(key); 00125 } 00126 } 00127 typename class_cache_t::iterator i = theCache.insert(theCache.end(), 00128 typename class_cache_t::value_type(cc, key)); 00129 theCacheIndex.insert(typename cache_index_t::value_type(key, i)); 00130 } 00132 template <typename T> 00133 T 00134 Cache<T>::getFromCache(const String& key) 00135 { 00136 MutexLock l(cacheGuard); 00137 T cc(CIMNULL); 00138 // look up key in the index 00139 typename cache_index_t::iterator ii = theCacheIndex.find(key); 00140 if (ii != theCacheIndex.end()) 00141 { 00142 // we've got it, now get the iterator 00143 typename class_cache_t::iterator i = ii->second; 00144 // get the class 00145 cc = i->first; 00146 // now move the class to the end of the list 00147 theCache.splice(theCache.end(),theCache,i); 00148 // because splice doesn't actually move the elements, we don't have to 00149 // update the iterator in theCacheIndex 00150 } 00151 return cc; 00152 } 00154 template <typename T> 00155 void 00156 Cache<T>::removeFromCache(const String& key) 00157 { 00158 MutexLock l(cacheGuard); 00159 typename cache_index_t::iterator i = theCacheIndex.find(key); 00160 if (i != theCacheIndex.end()) 00161 { 00162 typename class_cache_t::iterator ci = i->second; 00163 theCacheIndex.erase(i); 00164 theCache.erase(ci); 00165 } 00166 } 00168 template <typename T> 00169 void 00170 Cache<T>::clearCache() 00171 { 00172 MutexLock l(cacheGuard); 00173 theCache.clear(); 00174 theCacheIndex.clear(); 00175 } 00177 template <typename T> 00178 void 00179 Cache<T>::setMaxCacheSize(UInt32 max) 00180 { 00181 MutexLock l(cacheGuard); 00182 maxCacheSize = max; 00183 if (max != 0) 00184 { 00185 while (theCacheIndex.size() >= maxCacheSize) 00186 { 00187 if (!theCache.empty()) 00188 { 00189 String key = theCache.begin()->second; 00190 theCache.pop_front(); 00191 theCacheIndex.erase(key); 00192 } 00193 } 00194 } 00195 } 00196 00197 } // end namespace OW_NAMESPACE 00198 00199 #endif