blob: 14f1788b88b3a05c93d475a94dc1550a2439bc6a [file] [log] [blame]
John Park33858a32018-09-28 23:05:48 -07001#ifndef AOS_UTIL_LINKED_LIST_H_
2#define AOS_UTIL_LINKED_LIST_H_
Brian Silverman521e6ba2014-09-04 13:37:46 -04003
4#include <functional>
5
John Park33858a32018-09-28 23:05:48 -07006#include "aos/transaction/transaction.h"
Brian Silverman521e6ba2014-09-04 13:37:46 -04007
8namespace aos {
9namespace util {
10
11// Handles manipulating an intrusive linked list. T must look like the
12// following:
13// struct T {
14// ...
15// T *next;
16// ...
17// };
18// This class doesn't deal with creating or destroying them, so
19// constructors/destructors/other members variables/member functions are all
20// fine, but the next pointer must be there for this class to work.
21// This class will handle all manipulations of next. It does not need to be
22// initialized before calling Add and should not be changed afterwards.
23// next can (and probably should) be private if the appropriate instantiation of
24// this class is friended.
25template <class T>
26class LinkedList {
27 public:
28 T *head() const { return head_; }
29
30 bool Empty() const { return head() == nullptr; }
31
32 void Add(T *t) {
33 Add<0>(t, nullptr);
34 }
35
36 // restore_points (if non-null) will be used so the operation can be safely
37 // reverted at any point.
38 template <int number_works>
39 void Add(T *t, transaction::WorkStack<transaction::RestorePointerWork,
40 number_works> *restore_pointers) {
41 if (restore_pointers != nullptr) restore_pointers->AddWork(&t->next);
42 t->next = head();
43 if (restore_pointers != nullptr) restore_pointers->AddWork(&head_);
44 head_ = t;
45 }
46
47 void Remove(T *t) {
48 Remove<0>(t, nullptr);
49 }
50
51 // restore_points (if non-null) will be used so the operation can be safely
52 // reverted at any point.
53 template <int number_works>
54 void Remove(T *t, transaction::WorkStack<transaction::RestorePointerWork,
55 number_works> *restore_pointers) {
56 T **pointer = &head_;
57 while (*pointer != nullptr) {
58 if (*pointer == t) {
59 if (restore_pointers != nullptr) {
60 restore_pointers->AddWork(pointer);
61 }
62 *pointer = t->next;
63 return;
64 }
65 pointer = &(*pointer)->next;
66 }
Austin Schuhf257f3c2019-10-27 21:00:43 -070067 AOS_LOG(FATAL, "%p is not in the list\n", t);
Brian Silverman521e6ba2014-09-04 13:37:46 -040068 }
69
70 // Calls function for each element of the list.
71 // function can modify these elements in any way except touching the next
72 // pointer (including by calling other methods of this object).
73 void Each(::std::function<void(T *)> function) const {
74 T *c = head();
75 while (c != nullptr) {
76 T *const next = c->next;
77 function(c);
78 c = next;
79 }
80 }
81
82 // Returns the first element of the list where function returns true or
83 // nullptr if it returns false for all.
84 T *Find(::std::function<bool(const T *)> function) const {
85 T *c = head();
86 while (c != nullptr) {
87 if (function(c)) return c;
88 c = c->next;
89 }
90 return nullptr;
91 }
92
93 private:
94 T *head_ = nullptr;
95};
96
97// Keeps track of something along with a next pointer. Useful for things that
98// either have types without next pointers or for storing pointers to things
99// that belong in multiple lists.
100template <class V>
101struct LinkedListReference {
102 V item;
103
104 private:
105 friend class LinkedList<LinkedListReference>;
106
107 LinkedListReference *next;
108};
109
110} // namespace util
111} // namespace aos
112
John Park33858a32018-09-28 23:05:48 -0700113#endif // AOS_UTIL_LINKED_LIST_H_