Leaked source code of windows server 2003
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.

389 lines
11 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. bool updateExpiryOnFind
  198. );
  199. ~CacheBase() throw ();
  200. // Erases all entries from the cache.
  201. void clear() throw ();
  202. // Removes and releases the entry matching key. Returns true if successful.
  203. bool erase(const void* key) throw ();
  204. // Evict any eligible entries. Returns the number of entries evicted.
  205. ULONG evict() throw ();
  206. // Returns the entry with the given key or null if no such entry exists. The
  207. // caller is responsible for releasing the returned entry.
  208. CacheEntry* find(const void* key) throw ();
  209. // Insert a new entry in the cache. Returns 'true' if the entry was
  210. // successfully inserted. Note: this operation can only fail if
  211. // checkForDuplicates is true and the entry already exists.
  212. bool insert(
  213. CacheEntry& entry,
  214. bool checkForDuplicates = true
  215. ) throw ();
  216. // Removes and returns the entry with the given key or null if no such entry
  217. // exists. The caller is responsible for releasing the returned entry.
  218. CacheEntry* remove(const void* key) throw ();
  219. //////////
  220. // iterator for traversing the cache entries.
  221. //////////
  222. class iterator
  223. {
  224. public:
  225. iterator() throw () {}
  226. iterator(CacheEntry* entry) throw () : p(entry) { }
  227. CacheEntry& operator*() const throw ()
  228. { return *p; }
  229. CacheEntry* operator->() const throw ()
  230. { return p; }
  231. iterator& operator++() throw ()
  232. { p = p->nextInList(); return *this; }
  233. iterator operator++(int) throw ()
  234. { iterator tmp = *this; ++*this; return tmp; }
  235. iterator& operator--() throw ()
  236. { p = p->prevInList(); return *this; }
  237. iterator operator--(int) throw ()
  238. { iterator tmp = *this; --*this; return tmp; }
  239. bool operator==(const iterator& i) const throw ()
  240. { return p == i.p; }
  241. bool operator!=(const iterator& i) const throw ()
  242. { return p != i.p; }
  243. protected:
  244. CacheEntry* p;
  245. };
  246. // Iterators for traversing the cache from most to least recently used.
  247. iterator begin() const throw ()
  248. { return flink; }
  249. iterator end() const throw ()
  250. { return listAsEntry(); }
  251. protected:
  252. CacheEntry* flink; // Doubly-linked list of entries.
  253. CacheEntry* blink;
  254. ULONG64 ttl; // Time-to-live of cache entries.
  255. ULONG maxEntries; // Max number of entries in the cache.
  256. bool autoUpdate; // true if TTL should be updated in find.
  257. // Evict an eligible entries without grabbing the lock.
  258. void unsafe_evict() throw ();
  259. // Remove an entry without grabbing the lock.
  260. CacheEntry* unsafe_remove(const void* key) throw ();
  261. // Returns the list as if it were a CacheEntry.
  262. CacheEntry* listAsEntry() const throw ()
  263. {
  264. return (CacheEntry*)
  265. ((ULONG_PTR)&flink - FIELD_OFFSET(CacheEntry, flink));
  266. }
  267. // Add an entry to the front of the LRU list (i.e., it is the most recently
  268. // used entry.
  269. void push_front(CacheEntry* entry) throw ();
  270. };
  271. ///////////////////////////////////////////////////////////////////////////////
  272. //
  273. // CLASS
  274. //
  275. // Cache<T>
  276. //
  277. // DESCRIPTION
  278. //
  279. // Provides a type safe wrapper around CacheBase.
  280. //
  281. ///////////////////////////////////////////////////////////////////////////////
  282. template <class K, class T>
  283. class Cache : public CacheBase
  284. {
  285. public:
  286. Cache(
  287. HashKey hashFunction,
  288. ULONG initialSize,
  289. ULONG maxCapacity,
  290. ULONG timeToLive,
  291. bool updateExpiryOnFind
  292. ) throw ()
  293. : CacheBase(
  294. hashFunction,
  295. initialSize,
  296. maxCapacity,
  297. timeToLive,
  298. updateExpiryOnFind
  299. )
  300. { }
  301. bool erase(const K& key) throw ()
  302. { return CacheBase::erase(&key); }
  303. bool erase(const T& value) throw ()
  304. { return CacheBase::erase(value.getKey()); }
  305. ObjectPointer<T> find(const K& key) throw ()
  306. { return ObjectPointer<T>(narrow(CacheBase::find(&key)), false); }
  307. bool insert(
  308. T& entry,
  309. bool checkForDuplicates = true
  310. ) throw ()
  311. { return CacheBase::insert(entry, checkForDuplicates); }
  312. ObjectPointer<T> remove(const K& key) throw ()
  313. { return ObjectPointer<T>(narrow(CacheBase::remove(&key)), false); }
  314. protected:
  315. static T* narrow(CacheBase::Entry* entry) throw ()
  316. { return entry ? static_cast<T*>(entry) : NULL; }
  317. };
  318. #endif // IASCACHE_H