Roc Toolkit internal modules
Roc Toolkit: real-time audio streaming
list.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2015 Roc Streaming authors
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7  */
8 
9 //! @file roc_core/list.h
10 //! @brief Intrusive doubly-linked list.
11 
12 #ifndef ROC_CORE_LIST_H_
13 #define ROC_CORE_LIST_H_
14 
15 #include "roc_core/list_impl.h"
16 #include "roc_core/list_node.h"
17 #include "roc_core/noncopyable.h"
19 #include "roc_core/stddefs.h"
20 
21 namespace roc {
22 namespace core {
23 
24 //! Intrusive doubly-linked list.
25 //!
26 //! Does not perform allocations.
27 //! Provides O(1) size check, membership check, insertion, and removal.
28 //!
29 //! @tparam T defines object type, it must inherit ListNode.
30 //!
31 //! @tparam OwnershipPolicy defines ownership policy which is used to acquire an
32 //! element ownership when it's added to the list and release ownership when it's
33 //! removed from the list.
34 //!
35 //! @tparam Node defines base class of list nodes. It is needed if ListNode is
36 //! used with non-default tag.
37 template <class T,
38  template <class TT> class OwnershipPolicy = RefCountedOwnership,
39  class Node = ListNode<> >
40 class List : public NonCopyable<> {
41 public:
42  //! Pointer type.
43  //! @remarks
44  //! either raw or smart pointer depending on the ownership policy.
45  typedef typename OwnershipPolicy<T>::Pointer Pointer;
46 
47  //! Initialize empty list.
48  List() {
49  }
50 
51  //! Release ownership of containing objects.
52  ~List() {
53  while (!is_empty()) {
54  pop_back();
55  }
56  }
57 
58  //! Get number of elements in list.
59  size_t size() const {
60  return impl_.size();
61  }
62 
63  //! Check if size is zero.
64  bool is_empty() const {
65  return impl_.size() == 0;
66  }
67 
68  //! Check if element belongs to list.
69  bool contains(const T& elem) {
70  const ListData* data = to_node_data_(elem);
71  return impl_.contains(data);
72  }
73 
74  //! Get first list element.
75  //! @returns
76  //! first element or NULL if list is empty.
77  Pointer front() const {
78  ListData* data = impl_.front();
79  return from_node_data_(data);
80  }
81 
82  //! Get last list element.
83  //! @returns
84  //! last element or NULL if list is empty.
85  Pointer back() const {
86  ListData* data = impl_.back();
87  return from_node_data_(data);
88  }
89 
90  //! Get list element next to given one.
91  //!
92  //! @returns
93  //! list element following @p elem if @p elem is not
94  //! last, or NULL otherwise.
95  //!
96  //! @pre
97  //! @p elem should be member of this list.
98  Pointer nextof(T& elem) const {
99  ListData* data = to_node_data_(elem);
100  ListData* next_data = impl_.nextof(data);
101  return from_node_data_(next_data);
102  }
103 
104  //! Get list element previous to given one.
105  //!
106  //! @returns
107  //! list element preceding @p elem if @p elem is not
108  //! first, or NULL otherwise.
109  //!
110  //! @pre
111  //! @p elem should be member of this list.
112  Pointer prevof(T& elem) const {
113  ListData* data = to_node_data_(elem);
114  ListData* prev_data = impl_.prevof(data);
115  return from_node_data_(prev_data);
116  }
117 
118  //! Prepend element to list.
119  //!
120  //! @remarks
121  //! - prepends @p elem to list
122  //! - acquires ownership of @p elem
123  //!
124  //! @pre
125  //! @p elem should not be member of any list.
126  void push_front(T& elem) {
127  OwnershipPolicy<T>::acquire(elem);
128 
129  ListData* data = to_node_data_(elem);
130  impl_.insert(data, impl_.head()->next);
131  }
132 
133  //! Append element to list.
134  //!
135  //! @remarks
136  //! - appends @p elem to list
137  //! - acquires ownership of @p elem
138  //!
139  //! @pre
140  //! @p elem should not be member of any list.
141  void push_back(T& elem) {
142  OwnershipPolicy<T>::acquire(elem);
143 
144  ListData* data = to_node_data_(elem);
145  impl_.insert(data, impl_.head());
146  }
147 
148  //! Pop first element from list.
149  //!
150  //! @remarks
151  //! - removes first element of list
152  //! - releases ownership of removed element
153  //!
154  //! @pre
155  //! the list should not be empty.
156  void pop_front() {
157  ListData* data = impl_.pop_front();
158  T* elem = from_node_data_(data);
159 
160  OwnershipPolicy<T>::release(*elem);
161  }
162 
163  //! Pop last element from list.
164  //!
165  //! @remarks
166  //! - removes last element of list
167  //! - releases ownership of removed element
168  //!
169  //! @pre
170  //! the list should not be empty.
171  void pop_back() {
172  ListData* data = impl_.pop_back();
173  T* elem = from_node_data_(data);
174 
175  OwnershipPolicy<T>::release(*elem);
176  }
177 
178  //! Insert element into list.
179  //!
180  //! @remarks
181  //! - inserts @p elem before @p before
182  //! - acquires ownership of @p elem
183  //!
184  //! @pre
185  //! @p elem should not be member of any list.
186  //! @p before should be member of this list or NULL.
187  void insert_before(T& elem, T& before) {
188  OwnershipPolicy<T>::acquire(elem);
189 
190  ListData* data = to_node_data_(elem);
191  ListData* data_before = to_node_data_(before);
192  impl_.insert(data, data_before);
193  }
194 
195  //! Insert element into list.
196  //!
197  //! @remarks
198  //! - inserts @p elem after @p after
199  //! - acquires ownership of @p elem
200  //!
201  //! @pre
202  //! @p elem should not be member of any list.
203  //! @p after should be member of this list.
204  void insert_after(T& elem, T& after) {
205  OwnershipPolicy<T>::acquire(elem);
206 
207  ListData* data = to_node_data_(elem);
208  ListData* data_after = to_node_data_(after);
209  impl_.insert(data, data_after->next);
210  }
211 
212  //! Remove element from list.
213  //!
214  //! @remarks
215  //! - removes @p elem from list
216  //! - releases ownership of @p elem
217  //!
218  //! @pre
219  //! @p elem should be member of this list.
220  void remove(T& elem) {
221  ListData* data = to_node_data_(elem);
222  impl_.remove(data);
223 
224  OwnershipPolicy<T>::release(elem);
225  }
226 
227 private:
228  static ListData* to_node_data_(const T& elem) {
229  return static_cast<const Node&>(elem).list_data();
230  }
231 
232  static T* from_node_data_(ListData* data) {
233  return static_cast<T*>(static_cast<Node*>(Node::list_node(data)));
234  }
235 
236  ListImpl impl_;
237 };
238 
239 } // namespace core
240 } // namespace roc
241 
242 #endif // ROC_CORE_LIST_H_
ListData * front() const
Get first list node.
ListData * back() const
Get last list node.
ListData * pop_front()
Remove first node and return.
ListData * pop_back()
Remove last node and return.
ListData * prevof(ListData *node) const
Get list node previous to given one.
void remove(ListData *node)
Remove node from list.
void insert(ListData *node, ListData *before)
Insert node into list.
ListData * head()
Get list head (non-node node).
ListData * nextof(ListData *node) const
Get list node next to given one.
bool contains(const ListData *node) const
Check if node belongs to list.
size_t size() const
Get number of nodes in list.
Intrusive doubly-linked list.
Definition: list.h:40
List()
Initialize empty list.
Definition: list.h:48
Pointer prevof(T &elem) const
Get list element previous to given one.
Definition: list.h:112
Pointer nextof(T &elem) const
Get list element next to given one.
Definition: list.h:98
void remove(T &elem)
Remove element from list.
Definition: list.h:220
Pointer front() const
Get first list element.
Definition: list.h:77
~List()
Release ownership of containing objects.
Definition: list.h:52
size_t size() const
Get number of elements in list.
Definition: list.h:59
Pointer back() const
Get last list element.
Definition: list.h:85
OwnershipPolicy< T >::Pointer Pointer
Pointer type.
Definition: list.h:45
void pop_back()
Pop last element from list.
Definition: list.h:171
void push_front(T &elem)
Prepend element to list.
Definition: list.h:126
void insert_after(T &elem, T &after)
Insert element into list.
Definition: list.h:204
void insert_before(T &elem, T &before)
Insert element into list.
Definition: list.h:187
bool contains(const T &elem)
Check if element belongs to list.
Definition: list.h:69
void push_back(T &elem)
Append element to list.
Definition: list.h:141
void pop_front()
Pop first element from list.
Definition: list.h:156
bool is_empty() const
Check if size is zero.
Definition: list.h:64
Base class for non-copyable objects.
Definition: noncopyable.h:23
Intrusive doubly-linked list implementation.
Linked list node.
Root namespace.
Non-copyable object.
Ownership policies.
Commonly used types and functions.
List node internal data.
Definition: list_node.h:24
ListData * next
Next list element.
Definition: list_node.h:29