intrusive_list.hpp 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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. if ( this == & other ) return *this;
  127. clear(); // other than this, default
  128. node_ = other.node_;
  129. size_ = other.size_;
  130. head_ = other.head_;
  131. other.head_ = &other.end_;
  132. }
  133. intrusive_list& operator=( std::initializer_list<pointer> ilist ) {
  134. assign(ilist);
  135. }
  136. void assign( std::initializer_list<pointer> ilist ) {
  137. clear();
  138. for (pointer p : ilist) {
  139. push_back(p);
  140. }
  141. }
  142. inline pointer front() {
  143. return head_->get();
  144. }
  145. inline const_pointer front() const {
  146. return head_->get();
  147. }
  148. inline pointer back() {
  149. return end_.prev_->get();
  150. }
  151. inline const_pointer back() const {
  152. return end_.prev_->get();
  153. }
  154. inline iterator begin() noexcept {
  155. return iterator{head_};
  156. }
  157. inline const_iterator begin() const noexcept {
  158. return const_iterator{head_};
  159. }
  160. inline const_iterator cbegin() const noexcept {
  161. return const_iterator{head_};
  162. }
  163. inline iterator end() noexcept {
  164. return iterator{&end_};
  165. }
  166. inline const_iterator end() const noexcept {
  167. return const_iterator{&end_};
  168. }
  169. inline const_iterator cend() const noexcept {
  170. return const_iterator{&end_};
  171. }
  172. inline reverse_iterator rbegin() {
  173. return reverse_iterator{end()};
  174. }
  175. inline const_reverse_iterator rbegin() const noexcept {
  176. return const_reverse_iterator{end()};
  177. }
  178. inline const_reverse_iterator crbegin() const noexcept {
  179. return const_reverse_iterator{cend()};
  180. }
  181. inline reverse_iterator rend() noexcept {
  182. return reverse_iterator{begin()};
  183. }
  184. inline const_reverse_iterator rend() const noexcept {
  185. return const_reverse_iterator{begin()};
  186. }
  187. inline const_reverse_iterator crend() const noexcept{
  188. return const_reverse_iterator{cbegin()};
  189. }
  190. inline bool empty() const noexcept {
  191. return size_ = 0;
  192. }
  193. inline size_type size() const noexcept {
  194. return size_;
  195. }
  196. inline size_type max_size() const noexcept {
  197. return std::numeric_limits<size_type>::max();
  198. }
  199. void clear() noexcept {
  200. erase(begin(), end());
  201. }
  202. iterator insert(const_iterator pos, pointer value) {
  203. node_type* n = &(value->*node_);
  204. link(pos.get()->prev_, n);
  205. link(n, pos.get());
  206. n->list_ = this;
  207. ++size_;
  208. return iterator{n};
  209. }
  210. iterator insert(const_iterator pos, std::initializer_list<pointer> ilist) {
  211. for (pointer p : ilist) {
  212. link(pos.get()->prev_, p->*node_);
  213. link(p->*node_, pos.get());
  214. p->*node_->list_ = this;
  215. }
  216. size_ += ilist.size();
  217. return iterator{pos.get()};
  218. }
  219. iterator erase(iterator pos) {
  220. unlink(pos.get());
  221. pos.get()->list_ = nullptr;
  222. --size_;
  223. return iterator{pos.get()->next_};
  224. }
  225. iterator erase(iterator first, iterator last) {
  226. while (first != last) {
  227. first = erase(first);
  228. }
  229. return last;
  230. }
  231. inline void push_back(pointer value) {
  232. link(end_.prev_, &(value->*node_));
  233. ++size_;
  234. }
  235. inline void pop_back() {
  236. intrusive_node<T> *old = end_.prev_;
  237. end_.prev_ = old->prev_;
  238. unlink(old);
  239. --size_;
  240. }
  241. inline void push_front(pointer value) {
  242. insert(begin(), value);
  243. }
  244. inline void pop_front() {
  245. erase(begin());
  246. }
  247. void remove( pointer value ) {
  248. node_type* n = &(value->*node_);
  249. if (n->list_ == this) {
  250. unlink(n);
  251. --size_;
  252. }
  253. }
  254. template< class UnaryPredicate >
  255. void remove_if( UnaryPredicate pred ) {
  256. auto it = begin();
  257. while (it != end()) {
  258. pointer p = it.get()->ptr_;
  259. ++it;
  260. if (pred(p)) {
  261. remove(p);
  262. }
  263. }
  264. }
  265. private:
  266. inline void link(node_type* lhs, node_type* rhs) {
  267. lhs->next_ = rhs;
  268. rhs->prev_ = lhs;
  269. }
  270. inline void unlink(node_type* node) {
  271. if (node->next_) {
  272. node->next_->prev_ = node->prev_;
  273. }
  274. if (node->prev_) {
  275. node->prev_->next_ = node->next_;
  276. }
  277. }
  278. node_type T::*node_;
  279. node_type end_{nullptr}; // secretly const
  280. node_type *head_ = &end_;
  281. size_type size_;
  282. };
  283. #include "intrusive_iterator.tpp"
  284. #include "intrusive_node.tpp"