PX4 Firmware
PX4 Autopilot Software http://px4.io
IntrusiveQueue.hpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2019 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 #pragma once
35 
36 #include <stdlib.h>
37 
38 template<class T>
40 {
41 public:
42 
43  bool empty() const { return _head == nullptr; }
44 
45  T front() const { return _head; }
46  T back() const { return _tail; }
47 
48  size_t size() const
49  {
50  size_t sz = 0;
51 
52  for (auto node = front(); node != nullptr; node = node->next_intrusive_queue_node()) {
53  sz++;
54  }
55 
56  return sz;
57  }
58 
59  void push(T newNode)
60  {
61  // error, node already queued or already inserted
62  if ((newNode->next_intrusive_queue_node() != nullptr) || (newNode == _tail)) {
63  return;
64  }
65 
66  if (_head == nullptr) {
67  _head = newNode;
68  }
69 
70  if (_tail != nullptr) {
71  _tail->set_next_intrusive_queue_node(newNode);
72  }
73 
74  _tail = newNode;
75  }
76 
77  T pop()
78  {
79  T ret = _head;
80 
81  if (!empty()) {
82  if (_head != _tail) {
83  _head = _head->next_intrusive_queue_node();
84 
85  } else {
86  // only one item left
87  _head = nullptr;
88  _tail = nullptr;
89  }
90 
91  // clear next in popped (in might be re-inserted later)
92  ret->set_next_intrusive_queue_node(nullptr);
93  }
94 
95  return ret;
96  }
97 
98  bool remove(T removeNode)
99  {
100  // base case
101  if (removeNode == _head) {
102  if (_head->next_intrusive_queue_node() != nullptr) {
103  _head = _head->next_intrusive_queue_node();
104 
105  } else {
106  _head = nullptr;
107  }
108 
109  return true;
110  }
111 
112  for (T node = _head; node != nullptr; node = node->next_intrusive_queue_node()) {
113  // is sibling the node to remove?
114  if (node->next_intrusive_queue_node() == removeNode) {
115  // replace sibling
116  if (node->next_intrusive_queue_node() != nullptr) {
117  node->set_next_intrusive_queue_node(node->next_intrusive_queue_node()->next_intrusive_queue_node());
118 
119  } else {
120  node->set_next_intrusive_queue_node(nullptr);
121  }
122 
123  return true;
124  }
125  }
126 
127  return false;
128  }
129 
130  struct Iterator {
131  T node;
132  Iterator(T v) : node(v) {}
133 
134  operator T() const { return node; }
135  operator T &() { return node; }
136  T operator* () const { return node; }
138  {
139  if (node) {
140  node = node->next_intrusive_queue_node();
141  };
142 
143  return *this;
144  }
145  };
146 
147  Iterator begin() { return Iterator(_head); }
148  Iterator end() { return Iterator(nullptr); }
149 
150 private:
151 
152  T _head{nullptr};
153  T _tail{nullptr};
154 
155 };
156 
157 template<class T>
159 {
160 private:
162 
163  T next_intrusive_queue_node() const { return _next_intrusive_queue_node; }
164  void set_next_intrusive_queue_node(T new_next) { _next_intrusive_queue_node = new_next; }
165 
166  T _next_intrusive_queue_node{nullptr};
167 };
bool empty() const
size_t size() const
T next_intrusive_queue_node() const
void set_next_intrusive_queue_node(T new_next)
void push(T newNode)