1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
32 33 34 35
36
37 import xdc.rov.ViewInfo;
38
39 /*!
40 * ======== List ========
41 * Doubly Linked List Manager
42 *
43 * The List module makes available a set of functions that manipulate
44 * List objects accessed through handles of type List_Handle.
45 * Each List contains a linked sequence of zero or more elements
46 * referenced through variables of type List_Elem, which are typically
47 * embedded as the first field within a structure.
48 *
49 * All List function are atomic unless noted otherwise in the API
50 * descriptions. An atomic API means that the API completes in core
51 * functionality without being interrupted. Therefore, atomic APIs are
52 * thread-safe. An example is {@link #put}. Multiple threads can call
53 * {@link #put} at the same time. The threads do not have to manage the
54 * synchronization.
55 *
56 * The {@link xdc.runtime.Gate#enterSystem}/{@link xdc.runtime.Gate#leaveSystem}
57 * calls are used to make the APIs atomic. This Gate calls internally use
58 * {@link xdc.runtime.System}'s gate.
59 *
60 * The List module can be used both as a queue (i.e. First In First Out),
61 * as a stack (i.e. Last In First Out), or as a general purpose linked list.
62 *
63 * Lists are represented as doubly-linked lists, so calls to {@link #next}
64 * or {@link #prev} can loop continuously over the List.
65 * Refer to {@link #next} and {@link #prev} for examples.
66 *
67 * @a(List as a Queue)
68 *
69 * To treat the list object as a queue:
70 * @p(blist)
71 * -Use {@link #put} to put at the tail of the queue
72 * -Use {@link #get} to get from the head of the queue
73 * @p
74 *
75 * Here is sample code that acts on a List instance (listHandle) as a queue
76 * in a FIFO manner.
77 *
78 * @p(code)
79 * List_Elem elem[4];
80 * List_Elem *tmpElem;
81 *
82 * // place at the tail of the queue
83 * for (i = 0; i < 4; i++) {
84 * List_put(listHandle, &(elem[i]));
85 * }
86 *
87 * // remove the buffers from the head
88 * while((tmpElem = List_get(listHandle)) != NULL) {
89 * // process tmpElem
90 * }
91 * @p
92 *
93 * @a(List as a Stack)
94 *
95 * To treat the list object as a stack:
96 * @p(blist)
97 * -Use {@link #putHead} to put at the top of the stack
98 * -Use {@link #get} to get from the top of the stack
99 * @p
100 *
101 * Here is sample code that acts on a List instance (listHandle) as a stack
102 * in a LIFO manner.
103 *
104 * @p(code)
105 * List_Elem elem[4];
106 * List_Elem *tmpElem;
107 *
108 * // push onto the top (i.e. head)
109 * for (i = 0; i < 4; i++) {
110 * List_putHead(listHandle, &(elem[i]));
111 * }
112 *
113 * // remove the buffers in FIFO order.
114 * while((tmpElem = List_get(listHandle)) != NULL) {
115 * // process tmpElem
116 * }
117 * @p
118 */
119
120 module List
121 {
122 metaonly struct BasicView {
123 String label;
124 Ptr elems[];
125 }
126
127 @Facet
128 metaonly config ViewInfo.Instance rovViewInfo =
129 ViewInfo.create({
130 viewMap: [
131 ['Basic', {type: ViewInfo.INSTANCE, viewInitFxn: 'viewInitInstance', structName: 'BasicView'}]
132 ]
133 });
134
135 /*!
136 * ======== Elem ========
137 * Opaque List element
138 *
139 * A field of this type is placed at the head of client structs.
140 */
141 @Opaque struct Elem {
142 Elem *volatile next;
143 Elem *volatile prev;
144 };
145
146 /*!
147 * ======== elemClearMeta ========
148 * Clears a List element's pointers
149 *
150 * This API is not for removing elements from a List, and
151 * should never be called on an element in a List--only on deListed
152 * elements.
153 *
154 * @param(elem) element to be cleared
155 */
156 metaonly Void elemClearMeta(Elem *elem);
157
158 /*!
159 * ======== elemClear ========
160 * Clears a List element's pointers
161 *
162 * This API does not removing elements from a List, and
163 * should never be called on an element in a List--only on deListed
164 * elements.
165 *
166 * @param(elem) element to be cleared
167 */
168 Void elemClear(Elem *elem);
169
170 instance:
171
172 /*!
173 * ======== metaList ========
174 * @_nodoc
175 * Used to store elem before the object is initialized.
176 */
177 metaonly config any metaList[];
178
179 /*!
180 * ======== create ========
181 * Create a List object
182 */
183 create();
184
185 /*!
186 * ======== empty ========
187 * Test for an empty List (atomic)
188 *
189 * @b(returns) TRUE if this List is empty
190 */
191 Bool empty();
192
193 /*!
194 * ======== get ========
195 * Get element from front of List (atomic)
196 *
197 * This function atomically removes the element from the front of a
198 * List and returns a pointer to it.
199 *
200 * @b(returns) pointer to former first element or NULL if empty
201 */
202 Ptr get();
203
204 /*!
205 * ======== put ========
206 * Put element at end of List (atomic)
207 *
208 * This function atomically places the element at the end of
209 * List.
210 *
211 * @param(elem) pointer to new List element
212 */
213 Void put(Elem *elem);
214
215 /*!
216 * ======== putHead ========
217 * Put element at head of List (atomic)
218 *
219 * This function atomically places the element at the front of
220 * List.
221 *
222 * @param(elem) pointer to new List element
223 */
224 Void putHead(Elem *elem);
225
226 /*!
227 * ======== putMeta ========
228 * @_nodoc
229 * Put element at end of List.
230 *
231 * This meta function can be used to place an element onto
232 * the end of a list during configuration. There currently
233 * is no meta API to place the elem at the head of the list
234 * during configuration.
235 *
236 * @param(elem) pointer to new List element
237 */
238 metaonly Void putMeta(Elem* elem);
239
240 /*!
241 * ======== next ========
242 * Return next element in List (non-atomic)
243 *
244 * This function returns the next element on a list. It does not
245 * remove any items from the list. The caller should protect the
246 * list from being changed while using this call since it is non-atomic.
247 *
248 * To look at the first elem on the list, use NULL as the elem argument.
249 *
250 * This function is useful in searching a list. The following code shows
251 * an example. The scanning of a list should be protected against other
252 * threads that modify the list.
253 *
254 * @p(code)
255 * List_Elem *elem = NULL;
256 *
257 * // Begin protection against modification of the list.
258 *
259 * while ((elem = List_next(listHandle, elem)) != NULL) {
260 * //act elem as needed. For example call List_remove().
261 * }
262 *
263 * // End protection against modification of the list.
264 * @p
265 *
266 * @param(elem) element in list or NULL to start at the head
267 *
268 * @b(returns) next element in list or NULL to denote end
269 */
270 Ptr next(Elem *elem);
271
272 /*!
273 * ======== prev ========
274 * Return previous element in List (non-atomic)
275 *
276 * This function returns the previous element on a list. It does not
277 * remove any items from the list. The caller should protect the
278 * list from being changed while using this call since it is non-atomic.
279 *
280 * To look at the last elem on the list, use NULL as the elem argument.
281 *
282 * This function is useful in searching a list in reverse order. The
283 * following code shows an example. The scanning of a list should be
284 * protected against other threads that modify the list.
285 *
286 * @p(code)
287 * List_Elem *elem = NULL;
288 *
289 * // Begin protection against modification of the list.
290 *
291 * while ((elem = List_prev(listHandle, elem)) != NULL) {
292 * //act elem as needed. For example call List_remove().
293 * }
294 *
295 * // End protection against modification of the list.
296 * @p
297 *
298 * @param(elem) element in list or NULL to start at the end (i.e. tail)
299 *
300 * @b(returns) previous element in list or NULL to denote
301 * no previous elem
302 */
303 Ptr prev(Elem *elem);
304
305 /*!
306 * ======== insert ========
307 * Insert element at into a List (non-atomic)
308 *
309 * This function inserts `newElem` in the queue in
310 * front of `curElem`. The caller should protect the
311 * list from being changed while using this call since it is non-atomic.
312 *
313 * To place an elem at the end of the list, use {@link #put}.
314 * To place a elem at the front of the list, use {@link #putHead}.
315 *
316 * @param(newElem) element to insert
317 *
318 * @param(curElem) element to insert in front of
319 */
320 Void insert(Elem *newElem, Elem *curElem);
321
322 /*!
323 * ======== remove ========
324 * Remove elem from middle of list (non-atomic)
325 *
326 * This function removes an elem from a list.
327 * The `elem` parameter is a pointer to an existing element to be removed
328 * from the List. The caller should protect the
329 * list from being changed while using this call since it is non-atomic.
330 *
331 * @param(elem) element in list
332 */
333 Void remove(Elem *elem);
334
335 /*!
336 * ======== dequeue ========
337 * Get element from front of List (non-atomic)
338 *
339 * This function atomically removes the element from the front of a
340 * List and returns a pointer to it.
341 *
342 * @b(returns) pointer to former first element or NULL if empty
343 */
344 Ptr dequeue();
345
346 /*!
347 * ======== enqueue ========
348 * Put element at end of List (non-atomic)
349 *
350 * This function atomically places the element at the end of
351 * List.
352 *
353 * @param(elem) pointer to new List element
354 */
355 Void enqueue(Elem *elem);
356
357 /*!
358 * ======== enqueueHead ========
359 * Put element at head of List (non-atomic)
360 *
361 * This function atomically places the element at the front of
362 * List.
363 *
364 * @param(elem) pointer to new List element
365 */
366 Void enqueueHead(Elem *elem);
367
368 internal:
369
370
371 struct Instance_State {
372 Elem elem;
373 };
374 }
375 376 377
378