intrusive_list.hpp 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332
  1. //
  2. // intrusive_iterator.h
  3. // utilities
  4. //
  5. // Created by Sam Jaffe on 9/26/14.
  6. // Copyright (c) 2014 Sam Jaffe. All rights reserved.
  7. //
  8. #pragma once
  9. #include <iterator>
  10. #include <limits>
  11. #include <cstddef>
  12. template <typename T>
  13. class intrusive_node;
  14. template <typename T>
  15. class intrusive_list;
  16. template <typename T>
  17. class intrusive_iterator;
  18. template <typename T>
  19. class const_intrusive_iterator;
  20. template <typename T>
  21. class intrusive_node {
  22. public:
  23. typedef T value_type;
  24. typedef T& reference;
  25. typedef const T& const_reference;
  26. typedef T* pointer;
  27. typedef const T* const_pointer;
  28. private:
  29. typedef intrusive_node<T>* self;
  30. public:
  31. intrusive_node() = delete;
  32. intrusive_node(const intrusive_node&) = delete;
  33. intrusive_node(intrusive_node&&) = delete;
  34. intrusive_node& operator=(const intrusive_node&) = delete;
  35. intrusive_node& operator=(intrusive_node&&) = delete;
  36. intrusive_node(pointer ptr);
  37. ~intrusive_node();
  38. private:
  39. friend intrusive_list<T>;
  40. friend intrusive_iterator<intrusive_node<T> >;
  41. friend const_intrusive_iterator<intrusive_node<T> >;
  42. pointer ptr_ = nullptr;
  43. intrusive_list<T>* list_ = nullptr;
  44. self next_ = nullptr;
  45. self prev_ = nullptr;
  46. };
  47. template <typename N>
  48. class intrusive_iterator : public std::iterator<std::bidirectional_iterator_tag, typename N::value_type> {
  49. public:
  50. typedef std::bidirectional_iterator_tag iterator_category;
  51. typedef typename N::value_type value_type;
  52. typedef typename N::reference reference;
  53. typedef typename N::const_reference const_reference;
  54. typedef typename N::pointer pointer;
  55. typedef typename N::const_pointer const_pointer;
  56. public:
  57. intrusive_iterator(N* node);
  58. reference operator*();
  59. const_reference operator*() const;
  60. pointer operator->();
  61. const_pointer operator->() const;
  62. intrusive_iterator operator++(int);
  63. intrusive_iterator& operator++();
  64. intrusive_iterator operator--(int);
  65. intrusive_iterator& operator--();
  66. bool operator==(const intrusive_iterator& other) const;
  67. bool operator!=(const intrusive_iterator& other) const;
  68. private:
  69. friend intrusive_list<value_type>;
  70. N* get();
  71. const N* get() const;
  72. N* node_;
  73. };
  74. template <typename N>
  75. class const_intrusive_iterator : public std::iterator<std::bidirectional_iterator_tag, typename N::value_type> {
  76. public:
  77. typedef std::bidirectional_iterator_tag iterator_category;
  78. typedef typename N::value_type value_type;
  79. typedef typename N::reference reference;
  80. typedef typename N::const_reference const_reference;
  81. typedef typename N::pointer pointer;
  82. typedef typename N::const_pointer const_pointer;
  83. public:
  84. const_intrusive_iterator(const N* node);
  85. const_reference operator*() const;
  86. const_pointer operator->() const;
  87. const_intrusive_iterator operator++(int);
  88. const_intrusive_iterator& operator++();
  89. const_intrusive_iterator operator--(int);
  90. const_intrusive_iterator& operator--();
  91. bool operator==(const const_intrusive_iterator& other) const;
  92. bool operator!=(const const_intrusive_iterator& other) const;
  93. private:
  94. friend intrusive_list<value_type>;
  95. const N* get() const;
  96. const N* node_;
  97. };
  98. template <typename T>
  99. class intrusive_list {
  100. public:
  101. typedef T value_type;
  102. typedef intrusive_node<value_type> node_type;
  103. typedef std::size_t size_type;
  104. typedef std::ptrdiff_t difference_type;
  105. typedef T* pointer;
  106. typedef const T* const_pointer;
  107. typedef intrusive_iterator<node_type> iterator;
  108. typedef const_intrusive_iterator<node_type> const_iterator;
  109. typedef typename std::reverse_iterator<iterator> reverse_iterator;
  110. typedef typename std::reverse_iterator<const_iterator> const_reverse_iterator;
  111. public:
  112. constexpr intrusive_list( node_type T::*node ) :
  113. node_(node) {
  114. }
  115. intrusive_list( const intrusive_list& ) = delete;
  116. intrusive_list( intrusive_list&& other ) = default;
  117. intrusive_list( std::initializer_list<pointer> ilist, node_type T::*node ) :
  118. node_(node) {
  119. assign(ilist);
  120. }
  121. ~intrusive_list() {
  122. clear();
  123. }
  124. intrusive_list& operator=( const intrusive_list& ) = delete;
  125. intrusive_list& operator=( intrusive_list&& other ) {
  126. clear(); // other than this, default
  127. node_ = other.node_;
  128. size_ = other.size_;
  129. head_ = other.head_;
  130. other.head_ = &other.end_;
  131. }
  132. intrusive_list& operator=( std::initializer_list<pointer> ilist ) {
  133. assign(ilist);
  134. }
  135. void assign( std::initializer_list<pointer> ilist ) {
  136. clear();
  137. for (pointer p : ilist) {
  138. push_back(p);
  139. }
  140. }
  141. inline pointer front() {
  142. return head_->get();
  143. }
  144. inline const_pointer front() const {
  145. return head_->get();
  146. }
  147. inline pointer back() {
  148. return end_.prev_->get();
  149. }
  150. inline const_pointer back() const {
  151. return end_.prev_->get();
  152. }
  153. inline iterator begin() noexcept {
  154. return iterator{head_};
  155. }
  156. inline const_iterator begin() const noexcept {
  157. return const_iterator{head_};
  158. }
  159. inline const_iterator cbegin() const noexcept {
  160. return const_iterator{head_};
  161. }
  162. inline iterator end() noexcept {
  163. return iterator{&end_};
  164. }
  165. inline const_iterator end() const noexcept {
  166. return const_iterator{&end_};
  167. }
  168. inline const_iterator cend() const noexcept {
  169. return const_iterator{&end_};
  170. }
  171. inline reverse_iterator rbegin() {
  172. return reverse_iterator{end()};
  173. }
  174. inline const_reverse_iterator rbegin() const noexcept {
  175. return const_reverse_iterator{end()};
  176. }
  177. inline const_reverse_iterator crbegin() const noexcept {
  178. return const_reverse_iterator{cend()};
  179. }
  180. inline reverse_iterator rend() noexcept {
  181. return reverse_iterator{begin()};
  182. }
  183. inline const_reverse_iterator rend() const noexcept {
  184. return const_reverse_iterator{begin()};
  185. }
  186. inline const_reverse_iterator crend() const noexcept{
  187. return const_reverse_iterator{cbegin()};
  188. }
  189. inline bool empty() const noexcept {
  190. return size_ = 0;
  191. }
  192. inline size_type size() const noexcept {
  193. return size_;
  194. }
  195. inline size_type max_size() const noexcept {
  196. return std::numeric_limits<size_type>::max();
  197. }
  198. void clear() noexcept {
  199. erase(begin(), end());
  200. }
  201. iterator insert(const_iterator pos, pointer value) {
  202. node_type* n = &(value->*node_);
  203. link(pos.get()->prev_, n);
  204. link(n, pos.get());
  205. n->list_ = this;
  206. ++size_;
  207. return iterator{n};
  208. }
  209. iterator insert(const_iterator pos, std::initializer_list<pointer> ilist) {
  210. for (pointer p : ilist) {
  211. link(pos.get()->prev_, p->*node_);
  212. link(p->*node_, pos.get());
  213. p->*node_->list_ = this;
  214. }
  215. size_ += ilist.size();
  216. return iterator{pos.get()};
  217. }
  218. iterator erase(iterator pos) {
  219. unlink(pos.get());
  220. pos.get()->list_ = nullptr;
  221. --size_;
  222. return iterator{pos.get()->next_};
  223. }
  224. iterator erase(iterator first, iterator last) {
  225. while (first != last) {
  226. first = erase(first);
  227. }
  228. return last;
  229. }
  230. inline void push_back(pointer value) {
  231. link(end_.prev_, &(value->*node_));
  232. ++size_;
  233. }
  234. inline void pop_back() {
  235. intrusive_node<T> *old = end_.prev_;
  236. end_.prev_ = old->prev_;
  237. unlink(old);
  238. --size_;
  239. }
  240. inline void push_front(pointer value) {
  241. insert(begin(), value);
  242. }
  243. inline void pop_front() {
  244. erase(begin());
  245. }
  246. void remove( pointer value ) {
  247. node_type* n = &(value->*node_);
  248. if (n->list_ == this) {
  249. unlink(n);
  250. --size_;
  251. }
  252. }
  253. template< class UnaryPredicate >
  254. void remove_if( UnaryPredicate pred ) {
  255. auto it = begin();
  256. while (it != end()) {
  257. pointer p = it.get()->ptr_;
  258. ++it;
  259. if (pred(p)) {
  260. remove(p);
  261. }
  262. }
  263. }
  264. private:
  265. inline void link(node_type* lhs, node_type* rhs) {
  266. lhs->next_ = rhs;
  267. rhs->prev_ = lhs;
  268. }
  269. inline void unlink(node_type* node) {
  270. if (node->next_) {
  271. node->next_->prev_ = node->prev_;
  272. }
  273. if (node->prev_) {
  274. node->prev_->next_ = node->next_;
  275. }
  276. }
  277. node_type T::*node_;
  278. node_type end_{nullptr}; // secretly const
  279. node_type *head_ = &end_;
  280. size_type size_;
  281. };
  282. #include "intrusive_iterator.hpp"
  283. #include "intrusive_node.hpp"