1
/*
2
* \brief Queue with first-in first-out semantics
3
* \author Norman Feske
4
* \date 2008-08-15
5
*/
6
7
/*
8
* Copyright (C) 2008-2013 Genode Labs GmbH
9
*
10
* This file is part of the Genode OS framework, which is distributed
11
* under the terms of the GNU General Public License version 2.
12
*/
13
14
#
ifndef _INCLUDE__UTIL__FIFO_H_
15
#
define _INCLUDE__UTIL__FIFO_H_
16
17
#
include <base/printf.h>
18
19
namespace
Genode {
20
21
template
<
typename
>
class
Fifo;
22
template
<
typename
>
class
Fifo_element;
23
}
24
25
26
/**
27
* Fifo queue
28
*
29
* \param QT queue element type
30
*/
31
template
<
typename
QT
>
32
class
Genode::
Fifo
33
{
34
public
:
35
36
class
Element
37
{
38
protected
:
39
40
friend
class
Fifo;
41
42
QT *
_next;
43
bool _is_enqueued;
44
45
public
:
46
47
Element(
)
:
_next(
0)
,
_is_enqueued(
false)
{
}
48
49
/**
50
* Return true is fifo element is enqueued in a fifo
51
*/
52
bool
is_enqueued(
)
{
return
_is_enqueued
;
}
53
54
/**
55
* Return next element in queue
56
*/
57
QT *
next(
)
const
{
return
_next
;
}
58
}
;
59
60
private
:
61
62
QT *
_head;
/* oldest element */
63
Element *
_tail;
/* newest element */
64
65
public
:
66
67
/**
68
* Return true if queue is empty
69
*/
70
bool
empty(
)
{
return
_tail ==
0
;
}
71
72
/**
73
* Constructor
74
*/
75
Fifo(
)
:
_head(
0)
,
_tail(
0)
{
}
76
77
/**
78
* Return first queue element
79
*/
80
QT *
head(
)
const
{
return
_head
;
}
81
82
/**
83
* Remove element explicitely from queue
84
*/
85
void
remove(
QT *
qe
)
86
{
87
if
(
empty(
)
)
return
;
88
89
/* if specified element is the first of the queue */
90
if
(
qe ==
_head)
{
91
_head =
qe->
Element::
_next;
92
if
(
!
_head)
_tail =
0;
93
}
94
else
{
95
96
/* search specified element in the queue */
97
Element *
e =
_head;
98
while
(
e->
_next &&
(
e->
_next !=
qe)
)
99
e =
e->
_next;
100
101
/* element is not member of the queue */
102
if
(
!
e->
_next)
return
;
103
104
/* e->_next is the element to remove, skip it in list */
105
e->
Element::
_next =
e->
Element::
_next->
Element::
_next;
106
if
(
!
e->
Element::
_next)
_tail =
e;
107
}
108
109
qe->
Element::
_next =
0;
110
qe->
Element::
_is_enqueued =
0;
111
}
112
113
/**
114
* Attach element at the end of the queue
115
*/
116
void
enqueue(
QT *
e
)
117
{
118
e->
Fifo::
Element::
_next =
0;
119
e->
Fifo::
Element::
_is_enqueued =
true;
120
121
if
(
empty(
)
)
{
122
_tail =
_head =
e;
123
return
;
124
}
125
126
_tail->
Fifo::
Element::
_next =
e;
127
_tail =
e;
128
}
129
130
/**
131
* Remove head element from queue
132
*
133
* \return head element or 0 if queue is empty
134
*/
135
QT *
dequeue(
)
136
{
137
QT *
result =
_head;
138
139
/* check if queue has only one last element */
140
if
(
_head ==
_tail)
{
141
_head =
0;
142
_tail =
0;
143
}
else
144
_head =
_head->
Fifo::
Element::
_next;
145
146
/* mark fifo queue element as free */
147
if
(
result)
{
148
result->
Fifo::
Element::
_next =
0;
149
result->
Fifo::
Element::
_is_enqueued =
false;
150
}
151
152
return
result
;
153
}
154
}
;
155
156
157
/**
158
* Helper for using member variables as FIFO elements
159
*
160
* \param T type of compound object to be organized in a FIFO
161
*
162
* This helper allow the creation of FIFOs that use member variables to
163
* connect their elements. This way, the organized type does not need to
164
* publicly inherit `Fifo<QT>::Element`. Furthermore objects can easily
165
* be organized in multiple FIFOs by embedding multiple `Fifo_element`
166
* member variables.
167
*/
168
template
<
typename
T
>
169
class
Genode::
Fifo_element :
public
Fifo<
Fifo_element<
T
>
>
::
Element
170
{
171
T *
_object;
172
173
public
:
174
175
Fifo_element(
T *
object
)
:
_object(
object)
{
}
176
177
/**
178
* Get typed object pointer
179
*
180
* Zero-pointer save: Returns 0 if this pointer is 0 to
181
* cover the case of accessing an empty FIFO.
182
*/
183
inline
T *
object(
)
184
{
185
if
(
this)
{
return
_object
;
}
186
return
0
;
187
}
188
}
;
189
190
#
endif /* _INCLUDE__UTIL__FIFO_H_ */