2 * Copyright 2013 Haiku, Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
6 * Paweł Dziepak, pdziepak@quarnos.org
12 #include <util/Heap.h>
14 #include "scheduler_profiler.h"
17 template<typename Element
>
21 unsigned int fPriority
;
26 template<typename Element
>
27 class RunQueueLinkImpl
{
29 inline RunQueueLink
<Element
>* GetRunQueueLink();
32 RunQueueLink
<Element
> fRunQueueLink
;
35 template<typename Element
>
36 class RunQueueStandardGetLink
{
38 typedef RunQueueLink
<Element
> Link
;
41 inline Link
* operator()(Element
* element
) const;
44 template<typename Element
, RunQueueLink
<Element
> Element::*LinkMember
>
45 class RunQueueMemberGetLink
{
47 typedef RunQueueLink
<Element
> Link
;
50 inline Link
* operator()(Element
* element
) const;
53 #define RUN_QUEUE_TEMPLATE_LIST \
54 template<typename Element, unsigned int MaxPriority, typename GetLink>
55 #define RUN_QUEUE_CLASS_NAME RunQueue<Element, MaxPriority, GetLink>
57 template<typename Element
, unsigned int MaxPriority
,
58 typename GetLink
= RunQueueStandardGetLink
<Element
> >
64 ConstIterator(const RunQueue
<Element
,
65 MaxPriority
, GetLink
>* list
);
67 inline ConstIterator
& operator=(const ConstIterator
& other
);
75 inline void _FindNextPriority();
77 const RUN_QUEUE_CLASS_NAME
* fList
;
78 unsigned int fPriority
;
81 static GetLink sGetLink
;
86 inline status_t
GetInitStatus();
88 inline Element
* PeekMaximum() const;
90 inline void PushFront(Element
* element
, unsigned int priority
);
91 inline void PushBack(Element
* elementt
, unsigned int priority
);
93 inline void Remove(Element
* element
);
95 inline Element
* GetHead(unsigned int priority
) const;
97 inline ConstIterator
GetConstIterator() const;
100 struct PriorityEntry
: public HeapLinkImpl
<PriorityEntry
, unsigned int>
104 typedef Heap
<PriorityEntry
, unsigned int, HeapGreaterCompare
<unsigned int> >
107 status_t fInitStatus
;
109 PriorityEntry fPriorityEntries
[MaxPriority
+ 1];
110 PriorityHeap fPriorityHeap
;
112 Element
* fHeads
[MaxPriority
+ 1];
113 Element
* fTails
[MaxPriority
+ 1];
115 static GetLink sGetLink
;
119 template<typename Element
>
120 RunQueueLink
<Element
>::RunQueueLink()
128 template<typename Element
>
129 RunQueueLink
<Element
>*
130 RunQueueLinkImpl
<Element
>::GetRunQueueLink()
132 return &fRunQueueLink
;
136 template<typename Element
>
137 RunQueueLink
<Element
>*
138 RunQueueStandardGetLink
<Element
>::operator()(Element
* element
) const
140 return element
->GetRunQueueLink();
144 template<typename Element
, RunQueueLink
<Element
> Element::*LinkMember
>
145 RunQueueLink
<Element
>*
146 RunQueueMemberGetLink
<Element
, LinkMember
>::operator()(Element
* element
) const
148 return &(element
->*LinkMember
);
152 RUN_QUEUE_TEMPLATE_LIST
153 RUN_QUEUE_CLASS_NAME::ConstIterator::ConstIterator()
160 RUN_QUEUE_TEMPLATE_LIST
161 RUN_QUEUE_CLASS_NAME::ConstIterator::ConstIterator(const RunQueue
<Element
,
162 MaxPriority
, GetLink
>* list
)
170 RUN_QUEUE_TEMPLATE_LIST
171 typename
RUN_QUEUE_CLASS_NAME::ConstIterator
&
172 RUN_QUEUE_CLASS_NAME::ConstIterator::operator=(const ConstIterator
& other
)
175 fPriority
= other
.fPriority
;
182 RUN_QUEUE_TEMPLATE_LIST
184 RUN_QUEUE_CLASS_NAME::ConstIterator::HasNext() const
186 return fNext
!= NULL
;
190 RUN_QUEUE_TEMPLATE_LIST
192 RUN_QUEUE_CLASS_NAME::ConstIterator::Next()
196 Element
* current
= fNext
;
197 RunQueueLink
<Element
>* link
= sGetLink(fNext
);
207 RUN_QUEUE_TEMPLATE_LIST
209 RUN_QUEUE_CLASS_NAME::ConstIterator::Rewind()
211 ASSERT(fList
!= NULL
);
213 fPriority
= MaxPriority
;
214 fNext
= fList
->GetHead(fPriority
);
220 RUN_QUEUE_TEMPLATE_LIST
222 RUN_QUEUE_CLASS_NAME::ConstIterator::_FindNextPriority()
224 ASSERT(fList
!= NULL
);
226 while (fPriority
-- > 0) {
227 fNext
= fList
->GetHead(fPriority
);
234 RUN_QUEUE_TEMPLATE_LIST
235 RUN_QUEUE_CLASS_NAME::RunQueue()
238 fPriorityHeap(MaxPriority
+ 1)
240 memset(fHeads
, 0, sizeof(fHeads
));
241 memset(fTails
, 0, sizeof(fTails
));
245 RUN_QUEUE_TEMPLATE_LIST
247 RUN_QUEUE_CLASS_NAME::GetInitStatus()
253 RUN_QUEUE_TEMPLATE_LIST
255 RUN_QUEUE_CLASS_NAME::PeekMaximum() const
257 SCHEDULER_ENTER_FUNCTION();
259 PriorityEntry
* maxPriority
= fPriorityHeap
.PeekRoot();
260 if (maxPriority
== NULL
)
262 unsigned int priority
= PriorityHeap::GetKey(maxPriority
);
264 ASSERT(priority
<= MaxPriority
);
265 ASSERT(fHeads
[priority
] != NULL
);
267 Element
* element
= fHeads
[priority
];
269 ASSERT(sGetLink(element
)->fPriority
== priority
);
270 ASSERT(fTails
[priority
] != NULL
);
271 ASSERT(sGetLink(element
)->fPrevious
== NULL
);
277 RUN_QUEUE_TEMPLATE_LIST
279 RUN_QUEUE_CLASS_NAME::PushFront(Element
* element
,
280 unsigned int priority
)
282 SCHEDULER_ENTER_FUNCTION();
284 ASSERT(priority
<= MaxPriority
);
286 RunQueueLink
<Element
>* elementLink
= sGetLink(element
);
288 ASSERT(elementLink
->fPrevious
== NULL
);
289 ASSERT(elementLink
->fNext
== NULL
);
291 ASSERT((fHeads
[priority
] == NULL
&& fTails
[priority
] == NULL
)
292 || (fHeads
[priority
] != NULL
&& fTails
[priority
] != NULL
));
294 elementLink
->fPriority
= priority
;
295 elementLink
->fNext
= fHeads
[priority
];
296 if (fHeads
[priority
] != NULL
)
297 sGetLink(fHeads
[priority
])->fPrevious
= element
;
299 fTails
[priority
] = element
;
300 fPriorityHeap
.Insert(&fPriorityEntries
[priority
], priority
);
302 fHeads
[priority
] = element
;
306 RUN_QUEUE_TEMPLATE_LIST
308 RUN_QUEUE_CLASS_NAME::PushBack(Element
* element
,
309 unsigned int priority
)
311 SCHEDULER_ENTER_FUNCTION();
313 ASSERT(priority
<= MaxPriority
);
315 RunQueueLink
<Element
>* elementLink
= sGetLink(element
);
317 ASSERT(elementLink
->fPrevious
== NULL
);
318 ASSERT(elementLink
->fNext
== NULL
);
320 ASSERT((fHeads
[priority
] == NULL
&& fTails
[priority
] == NULL
)
321 || (fHeads
[priority
] != NULL
&& fTails
[priority
] != NULL
));
323 elementLink
->fPriority
= priority
;
324 elementLink
->fPrevious
= fTails
[priority
];
325 if (fTails
[priority
] != NULL
)
326 sGetLink(fTails
[priority
])->fNext
= element
;
328 fHeads
[priority
] = element
;
329 fPriorityHeap
.Insert(&fPriorityEntries
[priority
], priority
);
331 fTails
[priority
] = element
;
335 RUN_QUEUE_TEMPLATE_LIST
337 RUN_QUEUE_CLASS_NAME::Remove(Element
* element
)
339 SCHEDULER_ENTER_FUNCTION();
341 RunQueueLink
<Element
>* elementLink
= sGetLink(element
);
342 unsigned int priority
= elementLink
->fPriority
;
344 ASSERT(elementLink
->fPrevious
!= NULL
|| fHeads
[priority
] == element
);
345 ASSERT(elementLink
->fNext
!= NULL
|| fTails
[priority
] == element
);
347 if (elementLink
->fPrevious
!= NULL
)
348 sGetLink(elementLink
->fPrevious
)->fNext
= elementLink
->fNext
;
350 fHeads
[priority
] = elementLink
->fNext
;
351 if (elementLink
->fNext
!= NULL
)
352 sGetLink(elementLink
->fNext
)->fPrevious
= elementLink
->fPrevious
;
354 fTails
[priority
] = elementLink
->fPrevious
;
356 ASSERT((fHeads
[priority
] == NULL
&& fTails
[priority
] == NULL
)
357 || (fHeads
[priority
] != NULL
&& fTails
[priority
] != NULL
));
359 if (fHeads
[priority
] == NULL
) {
360 fPriorityHeap
.ModifyKey(&fPriorityEntries
[priority
], MaxPriority
+ 1);
361 ASSERT(fPriorityHeap
.PeekRoot() == &fPriorityEntries
[priority
]);
362 fPriorityHeap
.RemoveRoot();
365 elementLink
->fPrevious
= NULL
;
366 elementLink
->fNext
= NULL
;
370 RUN_QUEUE_TEMPLATE_LIST
372 RUN_QUEUE_CLASS_NAME::GetHead(unsigned int priority
) const
374 SCHEDULER_ENTER_FUNCTION();
376 ASSERT(priority
<= MaxPriority
);
377 return fHeads
[priority
];
381 RUN_QUEUE_TEMPLATE_LIST
382 typename
RUN_QUEUE_CLASS_NAME::ConstIterator
383 RUN_QUEUE_CLASS_NAME::GetConstIterator() const
385 return ConstIterator(this);
389 RUN_QUEUE_TEMPLATE_LIST
390 GetLink
RUN_QUEUE_CLASS_NAME::sGetLink
;
392 RUN_QUEUE_TEMPLATE_LIST
393 GetLink
RUN_QUEUE_CLASS_NAME::ConstIterator::sGetLink
;
396 #endif // RUN_QUEUE_H