Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

380 lines
10 KiB

  1. ///////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright (c) 2000, Microsoft Corp. All rights reserved.
  4. //
  5. // FILE
  6. //
  7. // iascache.h
  8. //
  9. // SYNOPSIS
  10. //
  11. // Declares the classes for creating hash tables and caches.
  12. //
  13. // MODIFICATION HISTORY
  14. //
  15. // 02/07/2000 Original version.
  16. //
  17. ///////////////////////////////////////////////////////////////////////////////
  18. #ifndef IASCACHE_H
  19. #define IASCACHE_H
  20. #if _MSC_VER >= 1000
  21. #pragma once
  22. #endif
  23. #include <iasobj.h>
  24. #include <iaswin32.h>
  25. class HashTableBase;
  26. ///////////////////////////////////////////////////////////////////////////////
  27. //
  28. // CLASS
  29. //
  30. // HashTableEntry
  31. //
  32. // DESCRIPTION
  33. //
  34. // Abstract base class for objects that will be stored in a hash table.
  35. //
  36. ///////////////////////////////////////////////////////////////////////////////
  37. class HashTableEntry
  38. {
  39. public:
  40. virtual void AddRef() throw () = 0;
  41. virtual void Release() throw () = 0;
  42. virtual const void* getKey() const throw () = 0;
  43. virtual bool matches(const void* key) const throw () = 0;
  44. friend class HashTableBase;
  45. protected:
  46. HashTableEntry* next;
  47. virtual ~HashTableEntry() throw ();
  48. };
  49. ///////////////////////////////////////////////////////////////////////////////
  50. //
  51. // CLASS
  52. //
  53. // HashTableBase
  54. //
  55. // DESCRIPTION
  56. //
  57. // Implements a simple hash table.
  58. //
  59. ///////////////////////////////////////////////////////////////////////////////
  60. class HashTableBase
  61. {
  62. public:
  63. // Entry type.
  64. typedef HashTableEntry Entry;
  65. typedef ULONG (WINAPI *HashKey)(const void*) throw ();
  66. HashTableBase(
  67. HashKey hashFunction,
  68. ULONG initialSize
  69. );
  70. ~HashTableBase() throw ();
  71. // Erases all entries from the table.
  72. void clear() throw ();
  73. // Removes and releases the entry matching key. Returns true if successful.
  74. bool erase(const void* key) throw ();
  75. // Returns the entry with the given key or null if no such entry exists. The
  76. // caller is responsible for releasing the returned entry.
  77. HashTableEntry* find(const void* key) throw ();
  78. // Insert a new entry in the cache. Returns 'true' if the entry was
  79. // successfully inserted. Note: this operation can only fail if
  80. // checkForDuplicates is true and the entry already exists.
  81. bool insert(
  82. HashTableEntry& entry,
  83. bool checkForDuplicates = true
  84. ) throw ();
  85. // Removes and returns the entry with the given key or null if no such entry
  86. // exists. The caller is responsible for releasing the returned entry.
  87. HashTableEntry* remove(const void* key) throw ();
  88. // Resize the hash table to have newSize buckets. Returns true if
  89. // successful.
  90. bool resize(ULONG newSize) throw ();
  91. protected:
  92. void lock() throw ()
  93. { monitor.lock(); }
  94. void unlock() throw ()
  95. { monitor.unlock(); }
  96. HashTableEntry* bucketAsEntry(size_t bucket) throw ()
  97. { return (HashTableEntry*)(table + bucket); }
  98. typedef HashTableEntry* Bucket;
  99. HashKey hash; // Hash function for hashing keys.
  100. Bucket* table; // Hash table of entries.
  101. ULONG buckets; // Number of buckets in the table.
  102. ULONG entries; // Number of entries in the table.
  103. CriticalSection monitor; // Synchronizes access to the table.
  104. // Not implemented.
  105. HashTableBase(const HashTableBase&) throw ();
  106. HashTableBase& operator=(const HashTableBase&) throw ();
  107. };
  108. ///////////////////////////////////////////////////////////////////////////////
  109. //
  110. // CLASS
  111. //
  112. // HashTable<T>
  113. //
  114. // DESCRIPTION
  115. //
  116. // Provides a type safe wrapper around HashTableBase.
  117. //
  118. ///////////////////////////////////////////////////////////////////////////////
  119. template <class K, class T>
  120. class HashTable : public HashTableBase
  121. {
  122. public:
  123. HashTable(
  124. HashKey hashFunction,
  125. ULONG initialSize
  126. ) throw ()
  127. : HashTableBase(hashFunction, initialSize)
  128. { }
  129. bool erase(const K& key) throw ()
  130. { return HashTableBase::erase(&key); }
  131. bool erase(const T& value) throw ()
  132. { return HashTableBase::erase(value.getKey()); }
  133. ObjectPointer<T> find(const K& key) throw ()
  134. { return ObjectPointer<T>(narrow(HashTableBase::find(&key)), false); }
  135. bool insert(
  136. T& entry,
  137. bool checkForDuplicates = true
  138. ) throw ()
  139. { return HashTableBase::insert(entry, checkForDuplicates); }
  140. ObjectPointer<T> remove(const K& key) throw ()
  141. { return ObjectPointer<T>(narrow(HashTableBase::remove(&key)), false); }
  142. protected:
  143. static T* narrow(HashTableBase::Entry* entry) throw ()
  144. { return entry ? static_cast<T*>(entry) : NULL; }
  145. };
  146. class CacheBase;
  147. ///////////////////////////////////////////////////////////////////////////////
  148. //
  149. // CLASS
  150. //
  151. // CacheEntry
  152. //
  153. // DESCRIPTION
  154. //
  155. // Abstract base class for objects that will be stored in a cache.
  156. //
  157. ///////////////////////////////////////////////////////////////////////////////
  158. class CacheEntry : public HashTableEntry
  159. {
  160. public:
  161. // Methods for traversing the doubly-linked list.
  162. CacheEntry* prevInList() const throw ();
  163. CacheEntry* nextInList() const throw ();
  164. protected:
  165. friend class CacheBase;
  166. // Removes the node from the list.
  167. void removeFromList() throw ();
  168. // Methods for manipulating the expiration time.
  169. bool isExpired(const ULONG64& now) const throw ();
  170. bool isExpired() const throw ();
  171. void setExpiry(ULONG64 ttl) throw ();
  172. CacheEntry* flink; // Allows this to be an entry in a doubly-linked list.
  173. CacheEntry* blink;
  174. ULONG64 expiry; // Expiration time.
  175. };
  176. ///////////////////////////////////////////////////////////////////////////////
  177. //
  178. // CLASS
  179. //
  180. // CacheBase
  181. //
  182. // DESCRIPTION
  183. //
  184. // Extends HashTableBase to add support for LRU and TTL based eviction.
  185. //
  186. ///////////////////////////////////////////////////////////////////////////////
  187. class CacheBase : protected HashTableBase
  188. {
  189. public:
  190. // Entry type
  191. typedef CacheEntry Entry;
  192. CacheBase(
  193. HashKey hashFunction,
  194. ULONG initialSize,
  195. ULONG maxCapacity,
  196. ULONG timeToLive
  197. );
  198. ~CacheBase() throw ();
  199. // Erases all entries from the cache.
  200. void clear() throw ();
  201. // Removes and releases the entry matching key. Returns true if successful.
  202. bool erase(const void* key) throw ();
  203. // Evict any eligible entries. Returns the number of entries evicted.
  204. ULONG evict() throw ();
  205. // Returns the entry with the given key or null if no such entry exists. The
  206. // caller is responsible for releasing the returned entry.
  207. CacheEntry* find(const void* key) throw ();
  208. // Insert a new entry in the cache. Returns 'true' if the entry was
  209. // successfully inserted. Note: this operation can only fail if
  210. // checkForDuplicates is true and the entry already exists.
  211. bool insert(
  212. CacheEntry& entry,
  213. bool checkForDuplicates = true
  214. ) throw ();
  215. // Removes and returns the entry with the given key or null if no such entry
  216. // exists. The caller is responsible for releasing the returned entry.
  217. CacheEntry* remove(const void* key) throw ();
  218. //////////
  219. // iterator for traversing the cache entries.
  220. //////////
  221. class iterator
  222. {
  223. public:
  224. iterator() throw () {}
  225. iterator(CacheEntry* entry) throw () : p(entry) { }
  226. CacheEntry& operator*() const throw ()
  227. { return *p; }
  228. CacheEntry* operator->() const throw ()
  229. { return p; }
  230. iterator& operator++() throw ()
  231. { p = p->nextInList(); return *this; }
  232. iterator operator++(int) throw ()
  233. { iterator tmp = *this; ++*this; return tmp; }
  234. iterator& operator--() throw ()
  235. { p = p->prevInList(); return *this; }
  236. iterator operator--(int) throw ()
  237. { iterator tmp = *this; --*this; return tmp; }
  238. bool operator==(const iterator& i) const throw ()
  239. { return p == i.p; }
  240. bool operator!=(const iterator& i) const throw ()
  241. { return p != i.p; }
  242. protected:
  243. CacheEntry* p;
  244. };
  245. // Iterators for traversing the cache from most to least recently used.
  246. iterator begin() const throw ()
  247. { return flink; }
  248. iterator end() const throw ()
  249. { return listAsEntry(); }
  250. protected:
  251. CacheEntry* flink; // Doubly-linked list of entries.
  252. CacheEntry* blink;
  253. ULONG64 ttl; // Time-to-live of cache entries.
  254. ULONG maxEntries; // Max number of entries in the cache.
  255. // Evict an eligible entries without grabbing the lock.
  256. void unsafe_evict() throw ();
  257. // Remove an entry without grabbing the lock.
  258. CacheEntry* unsafe_remove(const void* key) throw ();
  259. // Returns the list as if it were a CacheEntry.
  260. CacheEntry* listAsEntry() const throw ()
  261. {
  262. return (CacheEntry*)
  263. ((ULONG_PTR)&flink - FIELD_OFFSET(CacheEntry, flink));
  264. }
  265. // Add an entry to the front of the LRU list (i.e., it is the most recently
  266. // used entry.
  267. void push_front(CacheEntry* entry) throw ();
  268. };
  269. ///////////////////////////////////////////////////////////////////////////////
  270. //
  271. // CLASS
  272. //
  273. // Cache<T>
  274. //
  275. // DESCRIPTION
  276. //
  277. // Provides a type safe wrapper around CacheBase.
  278. //
  279. ///////////////////////////////////////////////////////////////////////////////
  280. template <class K, class T>
  281. class Cache : public CacheBase
  282. {
  283. public:
  284. Cache(
  285. HashKey hashFunction,
  286. ULONG initialSize,
  287. ULONG maxCapacity,
  288. ULONG timeToLive
  289. ) throw ()
  290. : CacheBase(hashFunction, initialSize, maxCapacity, timeToLive)
  291. { }
  292. bool erase(const K& key) throw ()
  293. { return CacheBase::erase(&key); }
  294. bool erase(const T& value) throw ()
  295. { return CacheBase::erase(value.getKey()); }
  296. ObjectPointer<T> find(const K& key) throw ()
  297. { return ObjectPointer<T>(narrow(CacheBase::find(&key)), false); }
  298. bool insert(
  299. T& entry,
  300. bool checkForDuplicates = true
  301. ) throw ()
  302. { return CacheBase::insert(entry, checkForDuplicates); }
  303. ObjectPointer<T> remove(const K& key) throw ()
  304. { return ObjectPointer<T>(narrow(CacheBase::remove(&key)), false); }
  305. protected:
  306. static T* narrow(CacheBase::Entry* entry) throw ()
  307. { return entry ? static_cast<T*>(entry) : NULL; }
  308. };
  309. #endif // IASCACHE_H