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.

378 lines
11 KiB

  1. // Registrar.h -- Registrar template class
  2. // (c) Copyright Schlumberger Technology Corp., unpublished work, created
  3. // 1999. This computer program includes Confidential, Proprietary
  4. // Information and is a Trade Secret of Schlumberger Technology Corp. All
  5. // use, disclosure, and/or reproduction is prohibited unless authorized
  6. // in writing. All Rights Reserved.
  7. #if !defined(SLBCSP_REGISTRAR_H)
  8. #define SLBCSP_REGISTRAR_H
  9. #include <map>
  10. #include <functional>
  11. #include <algorithm>
  12. #include "Guarded.h"
  13. #include "Registry.h"
  14. #include "MasterLock.h"
  15. template<class Key, class T, class Cmp = std::less<Key> >
  16. class Registrar
  17. {
  18. public:
  19. // Types
  20. typedef T *EnrolleeType;
  21. typedef Key KeyType;
  22. typedef std::map<Key, EnrolleeType, Cmp> CollectionType;
  23. typedef Registry<CollectionType> RegistryType;
  24. typedef Registry<CollectionType const> ConstRegistryType;
  25. // C'tors/D'tors
  26. // Operators
  27. // Operations
  28. // Removes the enrollee identified by the key from the registry.
  29. static void
  30. Discard(Key const &rkey);
  31. // Return the enrollee identified by the key, creating it if it
  32. // doesn't exist.
  33. static EnrolleeType
  34. Instance(Key const &rkey);
  35. // Access
  36. // Return the enrollee identified by the key if it exists, 0 otherwise.
  37. static EnrolleeType
  38. Find(Key const &rKey);
  39. static ConstRegistryType &
  40. Registry();
  41. // Predicates
  42. protected:
  43. // Types
  44. // C'tors/D'tors
  45. explicit
  46. Registrar(Key const &rkey); // allow subclassing
  47. virtual
  48. ~Registrar() = 0; // make base abstract
  49. // Operators
  50. // Operations
  51. // Puts the enrollee into the registry identified by the key if
  52. // not already listed.
  53. static void
  54. Enroll(Key const &rkey,
  55. EnrolleeType enrollee);
  56. // Removes an entry from the registry.
  57. static void
  58. RemoveEnrollee(Key const &rkey);
  59. // Inserts an entry into the registry.
  60. static void
  61. InsertEnrollee(Key const &rkey, EnrolleeType enrollee);
  62. // Operation to perform after removing the enrollee from the
  63. // registry. Default does nothing.
  64. virtual void
  65. DiscardHook();
  66. // Subclass must define
  67. // Factory Method, operation returning a new enrollee for the key
  68. static EnrolleeType
  69. DoInstantiation(Key const &rkey);
  70. // Operation to perform after putting the enrollee into the
  71. // registry. Default does nothing.
  72. virtual void
  73. EnrollHook();
  74. // Access
  75. // Predicates
  76. // Returns true if the enrollee should remain in the registry;
  77. // false otherwise. Default returns true.
  78. virtual bool
  79. KeepEnrolled();
  80. // Static Variables
  81. // Variables
  82. private:
  83. // Types
  84. typedef typename Registrar<Key, T, Cmp> *BaseType;
  85. typedef CollectionType::iterator Iterator;
  86. typedef CollectionType::value_type ValueType;
  87. // C'tors/D'tors
  88. Registrar(Registrar const &); // don't allow copies
  89. // Operators
  90. Registrar<Key, T> &
  91. operator=(Registrar const &); // don't allow initialization
  92. // Operations
  93. static void
  94. Discard(Iterator const &rit);
  95. static void
  96. RemoveEnrollee(Iterator const &rit);
  97. static EnrolleeType
  98. FindEnrollee(Key const &rkey);
  99. static void
  100. SetupRegistry();
  101. // Access
  102. static CollectionType &
  103. Collection();
  104. // Predicates
  105. static bool
  106. PassesReview(EnrolleeType enrollee);
  107. // Variables
  108. static RegistryType *m_pregistry;
  109. };
  110. ///////////////////////// TEMPLATE METHODS ///////////////////////////////
  111. /////////////////////////// PUBLIC /////////////////////////////////
  112. // C'tors/D'tors
  113. // Operators
  114. // Operations
  115. template<class Key, class T, class Cmp>
  116. void
  117. Registrar<Key, T, Cmp>::Discard(Key const &rkey)
  118. {
  119. if (m_pregistry)
  120. {
  121. Guarded<RegistryType *> gregistry(m_pregistry); // serialize registry access
  122. CollectionType &rcollection = Collection();
  123. Iterator it = rcollection.find(rkey);
  124. if (rcollection.end() != it)
  125. Discard(it);
  126. }
  127. }
  128. template<class Key, class T, class Cmp>
  129. Registrar<Key, T, Cmp>::EnrolleeType
  130. Registrar<Key, T, Cmp>::Instance(Key const &rkey)
  131. {
  132. // The Template Method pattern is used to allow the instantiator
  133. // of the template to specify how the the enrollee is found and,
  134. // if necessary, created. Template Method can be found in "Design
  135. // Patterns: Elements of Reusable Object-Oriented Software,"
  136. // Gamma, Helm, Johnson, Vlissides, Addison-Wesley
  137. SetupRegistry();
  138. Guarded<RegistryType *> gregistry(m_pregistry); // serialize registry access
  139. EnrolleeType enrollee = FindEnrollee(rkey);
  140. if (EnrolleeType() == enrollee)
  141. {
  142. enrollee = T::DoInstantiation(rkey);
  143. Enroll(rkey, enrollee);
  144. }
  145. return enrollee;
  146. }
  147. // Access
  148. template<class Key, class T, class Cmp>
  149. Registrar<Key, T, Cmp>::EnrolleeType
  150. Registrar<Key, T, Cmp>::Find(Key const &rkey)
  151. {
  152. EnrolleeType enrollee = EnrolleeType();
  153. if (m_pregistry)
  154. {
  155. Guarded<RegistryType *> guard(m_pregistry); // serialize registry access
  156. enrollee = FindEnrollee(rkey);
  157. }
  158. return enrollee;
  159. }
  160. template<class Key, class T, class Cmp>
  161. Registrar<Key, T, Cmp>::ConstRegistryType &
  162. Registrar<Key, T, Cmp>::Registry()
  163. {
  164. SetupRegistry();
  165. // this "safe" cast is necessary to enforce the constness of the collection
  166. return reinterpret_cast<ConstRegistryType &>(*m_pregistry);
  167. }
  168. // Predicates
  169. // Static Variables
  170. /////////////////////////// PROTECTED /////////////////////////////////
  171. // C'tors/D'tors
  172. template<class Key, class T, class Cmp>
  173. Registrar<Key, T, Cmp>::Registrar(Key const &rkey)
  174. {}
  175. template<class Key, class T, class Cmp>
  176. Registrar<Key, T, Cmp>::~Registrar()
  177. {}
  178. // Operators
  179. // Operations
  180. template<class Key, class T, class Cmp>
  181. void
  182. Registrar<Key, T, Cmp>::DiscardHook()
  183. {}
  184. template<class Key, class T, class Cmp>
  185. void
  186. Registrar<Key, T, Cmp>::EnrollHook()
  187. {}
  188. template<class Key, class T, class Cmp>
  189. void
  190. Registrar<Key, T, Cmp>::RemoveEnrollee(Key const &rkey)
  191. {
  192. if (m_pregistry)
  193. {
  194. Guarded<RegistryType *> gregistry(m_pregistry); // serialize registry access
  195. CollectionType &rcollection = Collection();
  196. Iterator it = rcollection.find(rkey);
  197. if (rcollection.end() != it)
  198. RemoveEnrollee(it);
  199. }
  200. }
  201. template<class Key, class T, class Cmp>
  202. void
  203. Registrar<Key, T, Cmp>::InsertEnrollee(Key const &rkey,
  204. Registrar<Key, T, Cmp>::EnrolleeType enrollee)
  205. {
  206. ValueType registration(rkey, enrollee);
  207. Guarded<RegistryType *> guard(m_pregistry); // serialize registry access
  208. Collection().insert(registration);
  209. }
  210. // Access
  211. // Predicates
  212. template<class Key, class T, class Cmp>
  213. bool
  214. Registrar<Key, T, Cmp>::KeepEnrolled()
  215. {
  216. return true;
  217. }
  218. template<class Key, class T, class Cmp>
  219. void
  220. Registrar<Key, T, Cmp>::Enroll(Key const &rkey,
  221. Registrar<Key, T, Cmp>::EnrolleeType enrollee)
  222. {
  223. Guarded<RegistryType *> guard(m_pregistry); // serialize registry access
  224. InsertEnrollee(rkey, enrollee);
  225. BaseType base = enrollee;
  226. base->EnrollHook();
  227. }
  228. /////////////////////////// PRIVATE /////////////////////////////////
  229. // C'tors/D'tors
  230. // Operators
  231. // Operations
  232. template<class Key, class T, class Cmp>
  233. void
  234. Registrar<Key, T, Cmp>::Discard(Registrar<Key, T, Cmp>::Iterator const &rit)
  235. {
  236. BaseType base = rit->second;
  237. RemoveEnrollee(rit);
  238. base->DiscardHook();
  239. }
  240. template<class Key, class T, class Cmp>
  241. void
  242. Registrar<Key, T, Cmp>::RemoveEnrollee(Registrar<Key, T, Cmp>::Iterator const &rit)
  243. {
  244. Collection().erase(rit);
  245. }
  246. template<class Key, class T, class Cmp>
  247. Registrar<Key, T, Cmp>::EnrolleeType
  248. Registrar<Key, T, Cmp>::FindEnrollee(Key const &rkey)
  249. {
  250. EnrolleeType enrollee = EnrolleeType();
  251. CollectionType &rcollection = Collection();
  252. if (!rcollection.empty())
  253. {
  254. Iterator it = rcollection.find(rkey);
  255. if (rcollection.end() != it)
  256. {
  257. enrollee = it->second;
  258. if (!PassesReview(enrollee))
  259. {
  260. Discard(it);
  261. enrollee = EnrolleeType();
  262. }
  263. }
  264. }
  265. return enrollee;
  266. }
  267. template<class Key, class T, class Cmp>
  268. void
  269. Registrar<Key, T, Cmp>::SetupRegistry()
  270. {
  271. // Use Double-Checked Lock pattern for proper setup in the case of
  272. // preemptive multi-threading
  273. if (!m_pregistry)
  274. {
  275. Guarded<Lockable *> gmaster(&TheMasterLock());
  276. if (!m_pregistry)
  277. m_pregistry = new RegistryType;
  278. }
  279. }
  280. // Access
  281. template<class Key, class T, class Cmp>
  282. Registrar<Key, T, Cmp>::CollectionType &
  283. Registrar<Key, T, Cmp>::Collection()
  284. {
  285. return (*m_pregistry)();
  286. }
  287. // Predicates
  288. template<class Key, class T, class Cmp>
  289. bool
  290. Registrar<Key, T, Cmp>::PassesReview(Registrar<Key, T, Cmp>::EnrolleeType enrollee)
  291. {
  292. bool fPassed = false;
  293. if (EnrolleeType() != enrollee)
  294. {
  295. BaseType base = enrollee;
  296. fPassed = base->KeepEnrolled();
  297. }
  298. return fPassed;
  299. }
  300. #endif // SLBCSP_REGISTRAR_H