Advertisement
Guest User

Untitled

a guest
Jul 20th, 2017
56
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.49 KB | None | 0 0
  1. ////////////////////////////////////////////
  2. // Author: Reggie Meisler
  3. // Brief: Singly and doubly linked
  4. // intrusive list classes. Much more
  5. // efficient than the traditional
  6. // std::list style implementation.
  7. ////////////////////////////////////////////
  8. // Example use:
  9. //
  10. // class A
  11. // {
  12. // public:
  13. //
  14. // // A can be in multiple intrusive lists!
  15. // DLink<A> mLinkToBList;
  16. // SLink<A> mLinkToCList;
  17. //
  18. // };
  19. //
  20. // class B
  21. // {
  22. // public:
  23. //
  24. // IntrusiveDList<A, &A::mLinkToBList> mList;
  25. //
  26. // };
  27. //
  28. // class C
  29. // {
  30. // public:
  31. //
  32. // IntrusiveSList<A, &A::mLinkToCList> mList;
  33. //
  34. // };
  35. //
  36. ////////////////////////////////////////////
  37.  
  38. #pragma once
  39.  
  40.  
  41. namespace MF
  42. {
  43.  
  44. template <typename T>
  45. struct DLink
  46. {
  47. T* next;
  48. T* prev;
  49. };
  50.  
  51.  
  52. template <typename T>
  53. struct SLink
  54. {
  55. T* next;
  56. };
  57.  
  58.  
  59. // Helper function, to grab member pointer offset value
  60. // (Since member pointers are secretly just offsets from the this pointer,
  61. // all we do is cast the given value to an unsigned integer)
  62. template<typename Parent, typename Member>
  63. inline ptrdiff_t PointerToMemberOffset(const Member (Parent::*ptrToMember))
  64. {
  65. return *(unsigned int*)(void*)&ptrToMember;
  66. }
  67.  
  68.  
  69. // Implementation class, allows for a lot of flexibility in its type definitions
  70. template <typename T, typename U, template <typename Y> class LinkType, LinkType<T> (U::*linkPtr) = &U::link>
  71. class BaseIntrusiveDList
  72. {
  73. public:
  74.  
  75. BaseIntrusiveDList()
  76. {
  77. Clear();
  78. }
  79.  
  80. static void Unlink(T* node)
  81. {
  82. GetNext(GetPrev(node)) = GetNext(node);
  83. GetPrev(GetNext(node)) = GetPrev(node);
  84. }
  85.  
  86. void PushBack(T* node)
  87. {
  88. // Insert node before dummy
  89. GetNext(node) = GetNode(mDummy);
  90. GetPrev(node) = mDummy.prev;
  91. mDummy.prev = node;
  92. GetNext(GetPrev(node)) = node;
  93. }
  94.  
  95. void PushFront(T* node)
  96. {
  97. // Insert node after dummy
  98. GetNext(node) = mDummy.next;
  99. mDummy.next = node;
  100. GetPrev(node) = GetNode(mDummy);
  101. GetPrev(GetNext(node)) = node;
  102. }
  103.  
  104. T* PopBack()
  105. {
  106. // Remove node from before dummy
  107. T* node = mDummy.prev;
  108.  
  109. GetNext(GetPrev(mDummy.prev)) = GetNode(mDummy);
  110. mDummy.prev = GetPrev(mDummy.prev);
  111.  
  112. return node;
  113. }
  114.  
  115. T* PopFront()
  116. {
  117. // Remove node from after dummy
  118. T* node = mDummy.next;
  119.  
  120. GetPrev(GetNext(mDummy.next)) = GetNode(mDummy);
  121. mDummy.next = GetNext(mDummy.next);
  122.  
  123. return node;
  124. }
  125.  
  126. // Cheap and dirty way of clearing out list
  127. void Clear()
  128. {
  129. mDummy.next = GetNode(mDummy);
  130. mDummy.prev = GetNode(mDummy);
  131. }
  132.  
  133. T* GetFirst()
  134. {
  135. return mDummy.next;
  136. }
  137.  
  138. T* GetLast()
  139. {
  140. return GetNode(mDummy);
  141. }
  142.  
  143. bool Empty() const
  144. {
  145. return mDummy.next == GetNode(mDummy);
  146. }
  147.  
  148. void Iterate(T*& itr)
  149. {
  150. itr = GetNext(itr);
  151. }
  152.  
  153. protected:
  154.  
  155. // Non-copyable
  156. BaseIntrusiveDList(const BaseIntrusiveDList&);
  157. void operator=(const BaseIntrusiveDList&);
  158.  
  159. // Handy conversion functions from link to node and vice versa
  160. static LinkType<T>& GetLink(T* node)
  161. {
  162. return ((U*)node->*linkPtr);
  163. }
  164.  
  165. static T*& GetNext(T* node)
  166. {
  167. return GetLink(node).next;
  168. }
  169.  
  170. static T*& GetPrev(T* node)
  171. {
  172. return GetLink(node).prev;
  173. }
  174.  
  175. static T* GetNode(LinkType<T>& link)
  176. {
  177. return (T*)((unsigned char*)&link - PointerToMemberOffset(linkPtr));
  178. }
  179.  
  180. static const T* GetNode(const LinkType<T>& link)
  181. {
  182. return (T*)((unsigned char*)&link - PointerToMemberOffset(linkPtr));
  183. }
  184.  
  185. LinkType<T>& GetDummy() const
  186. {
  187. return mDummy;
  188. }
  189.  
  190. private:
  191.  
  192. LinkType<T> mDummy;
  193.  
  194. };
  195.  
  196.  
  197. // Implementation class, allows for a lot of flexibility in its type definitions
  198. // - Optimized, non-circular, essentially acts like a stack
  199. template <typename T, typename U, template <typename Y> class LinkType, LinkType<T> (U::*linkPtr) = &U::link>
  200. class BaseIntrusiveSList
  201. {
  202. public:
  203.  
  204. BaseIntrusiveSList()
  205. {
  206. mDummy.next = GetNode(mDummy);
  207. }
  208.  
  209. void PushFront(T* node)
  210. {
  211. // Push onto front of list
  212. GetNext(node) = mDummy.next;
  213. mDummy.next = node;
  214. }
  215.  
  216. T* PopFront()
  217. {
  218. T* node = mDummy.next;
  219. mDummy.next = GetNext(mDummy.next);
  220.  
  221. return node;
  222. }
  223.  
  224. // Cheap and dirty way of clearing out list
  225. void Clear()
  226. {
  227. // Since we're an intrusive list, we are not responsible for memory cleanup!
  228. mDummy.next = GetNode(mDummy);
  229. }
  230.  
  231. bool Contains(T* node) const
  232. {
  233. T* itr = GetNext(mDummy);
  234.  
  235. // Empty list
  236. if( itr == NULL )
  237. return;
  238.  
  239. // Loop around list looking for node
  240. while( itr != GetNode(mDummy) && GetNext(itr) != node )
  241. {
  242. itr = GetNext(itr);
  243. }
  244.  
  245. return itr != GetNode(mDummy);
  246. }
  247.  
  248. T* GetFirst()
  249. {
  250. return mDummy.next;
  251. }
  252.  
  253. T* GetLast()
  254. {
  255. return GetNode(mDummy);
  256. }
  257.  
  258. const T* GetFirst() const
  259. {
  260. return mDummy.next;
  261. }
  262.  
  263. const T* GetLast() const
  264. {
  265. return GetNode(mDummy);
  266. }
  267.  
  268. bool Empty()
  269. {
  270. return mDummy.next == GetNode(mDummy);
  271. }
  272.  
  273. void Iterate(T*& itr)
  274. {
  275. itr = GetNext(itr);
  276. }
  277.  
  278. protected:
  279.  
  280. // Non-copyable
  281. BaseIntrusiveSList(const BaseIntrusiveSList&);
  282. void operator=(const BaseIntrusiveSList&);
  283.  
  284. // Handy conversion functions from link to node and vice versa
  285. static LinkType<T>& GetLink(T* node)
  286. {
  287. return ((U*)node->*linkPtr);
  288. }
  289.  
  290. static T*& GetNext(T* node)
  291. {
  292. return GetLink(node).next;
  293. }
  294.  
  295. static T* GetNode(const SLink<T>& link)
  296. {
  297. return (T*)((unsigned char*)&link - PointerToMemberOffset(linkPtr));
  298. }
  299.  
  300. LinkType<T>& GetDummy() const
  301. {
  302. return mDummy;
  303. }
  304.  
  305. private:
  306.  
  307. LinkType<T> mDummy;
  308.  
  309. };
  310.  
  311.  
  312. // Common-use classes
  313. template <typename T, DLink<T> (T::*linkPtr) = &T::mLink>
  314. class IntrusiveDList : public BaseIntrusiveDList<T, T, DLink, linkPtr> {};
  315.  
  316. template <typename T, SLink<T> (T::*linkPtr) = &T::mLink>
  317. class IntrusiveSList : public BaseIntrusiveSList<T, T, SLink, linkPtr> {};
  318.  
  319. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement