6 #include "member_offs.h"
11 * Priority sorted list with insert complexity O(n) n = number of available
12 * priorities (256 in Fiasco).
19 * Priority sorted list.
21 * The list is organized in a way that the highest priority member can be
22 * found with O(1). Ever dequeue operation is also O(1).
24 * There is a forward iteratable list with at most one element per priority.
25 * Elements with the same priority are handled in a double-linked circular
26 * list for each priority. This double-linked list implements FIFO policy for
27 * finding the next element.
29 class Prio_list : private cxx::H_list<Prio_list_elem>
32 friend class Jdb_sender_list;
34 typedef cxx::H_list<Prio_list_elem> P_list;
35 typedef cxx::D_list_cyclic<Prio_list_elem> S_list;
40 Prio_list_elem *first() const { return front(); }
43 class Iteratable_prio_list : public Prio_list
46 Spin_lock<> *lock() { return &_lock; }
49 Prio_list_elem *_cursor;
53 typedef Iteratable_prio_list Locked_prio_list;
57 * Single element of a priority sorted list.
59 class Prio_list_elem : public cxx::H_list_item, public cxx::D_list_item
63 friend class Prio_list;
64 friend class Jdb_sender_list;
65 typedef cxx::D_list_cyclic<Prio_list_elem> S_list;
68 * Priority, the higher the better.
78 * Setup pointers for enqueue.
82 Prio_list_elem::init(unsigned short p)
92 Prio_list_elem::prio() const
97 Prio_list::next(Prio_list_elem *e) const
99 S_list::Iterator i = ++S_list::iter(e);
100 if (P_list::in_list(*i))
101 return *++P_list::iter(*i);
106 * Insert a new element into the priority list.
107 * @param e the element to insert
108 * @param prio the priority for the element
110 PUBLIC inline NEEDS[Prio_list_elem::init]
112 Prio_list::insert(Prio_list_elem *e, unsigned short prio)
117 Iterator pos = begin();
119 while (pos != end() && pos->prio() > prio)
122 if (pos != end() && pos->prio() == prio)
123 S_list::insert_before(e, S_list::iter(*pos));
126 S_list::self_insert(e);
127 insert_before(e, pos);
132 * Is the element actually enqueued?
133 * @return true if the element is actaully enqueued in a list.
136 bool Prio_list_elem::in_list() const { return S_list::in_list(this); }
139 * Dequeue a given element from the list.
140 * @param e the element to dequeue
144 Prio_list::dequeue(Prio_list_elem *e, Prio_list_elem **next = 0)
146 if (P_list::in_list(e))
148 assert (S_list::in_list(e));
149 // yes we are the head of our priority
150 if (S_list::has_sibling(e))
152 P_list::replace(e, *++S_list::iter(e));
153 if (next) *next = *++S_list::iter(e);
157 if (next) *next = *++P_list::iter(e);
165 if (P_list::in_list(*++S_list::iter(e))) // actually we are the last on our priority
166 *next = *++P_list::iter(e);
168 *next = *++S_list::iter(e);
175 Iteratable_prio_list::Iteratable_prio_list() : _cursor(0), _lock(Spin_lock<>::Unlocked) {}
178 * Dequeue a given element from the list.
179 * @param e the element to dequeue
181 PUBLIC inline NEEDS[Prio_list::dequeue]
183 Iteratable_prio_list::dequeue(Prio_list_elem *e)
185 Prio_list_elem **c = 0;
186 if (EXPECT_FALSE(_cursor != 0) && EXPECT_FALSE(_cursor == e))
189 Prio_list::dequeue(e, c);
194 Iteratable_prio_list::cursor(Prio_list_elem *e)
199 Iteratable_prio_list::cursor() const