Minimal example of TAILQ usage out of <sys/queue.h> library
Asked Answered
J

2

22

Can some one provide minimal example of TAILQ usage out of linux system library with explanation in c which can be compiled using gcc in Linux?

Jennine answered 11/3, 2014 at 2:21 Comment(0)
G
43

The TAILQ_ENTRY macro is used to establish the pointers used to insert items into the list. You place it into your structure that you want to list up.

struct foo {
    TAILQ_ENTRY(foo) tailq;
    int datum;
    /* ... */
};

The TAILQ_HEAD is used to define a structure that will act as the container for your link list elements. You provide it with a structure name, and the name of the type that it will contain.

TAILQ_HEAD(fooq, foo);

Use TAILQ_INIT to initialize an instance of your list container.

struct fooq q;
TAILQ_INIT(&q);

Use the TAILQ_INSERT_* macros to add elements.

struct foo data[3] = { foo(3), foo(7), foo(1) };
TAILQ_INSERT_HEAD(&q, &data[0], tailq);
TAILQ_INSERT_AFTER(&q, &data[0], &data[1], tailq);
TAILQ_INSERT_TAIL(&q, &data[2], tailq);

You can use TAILQ_FOREACH and TAILQ_FOREACH_REVERSE to traverse the list.

struct foo *p;
TAILQ_FOREACH(p, &q, tailq) {
    printf(" %d", p->datum);
}
puts("");

If you want to iterate over the list while removing all its elements, it is probably easier to use a while loop and use the TAILQ_EMPTY and TAILQ_FIRST macros.

while (!TAILQ_EMPTY(&q)) {
    p = TAILQ_FIRST(&q);
    TAILQ_REMOVE(&q, p, tailq);
    /* ... */
}

The above code was mostly taken verbatim from an example I wrote and tested on IDEONE.

Grizelda answered 11/3, 2014 at 7:26 Comment(9)
Try it online!Grizelda
A nice but confusing example. Calling everything 'foo*' including 'struct foo ... and function foo() should be part of a code obfuscation contest.Lalla
@Lalla It is fairly common to indicate different data structures are related by name. In this case, a fooq is a queue container for foo structures.Grizelda
Related, yet different means you need a distinguishing name. . fooq as a pointer of 'struct foo' elements might get a pass,, but the peculiar and unnecessary partial initializer function 'foo' is over the top.Lalla
@Lalla As you noted, the function name matches the name of the structure it is initializing.Grizelda
Which, in C is overloading the term 'foo'. bar, bletch qux exist for a reason.Lalla
@Lalla I am just indicating the names coinciding is a feature. Search replace with a suitably different name makes the code just as usable to the same effect. I understand it is not to everyone's liking.Grizelda
C doesn't have constructors, so overloading namespace with a function 'foo' and a struct 'foo' simply makes the C code less-readable. new_foo() or mk_foo() would be more readable, if the trivial function wasn't extraneous & excessive for the example.Lalla
@Lalla I appreciate your continued input. I hope we both can agree that not everyone will agree on coding styles and what constitutes readable code.Grizelda
L
1

Tho' jxh code/link above is algorithmically a nice example for TAILQ. I believe this a a more readable and didactic transliteration:

#include <stdio.h>
#include <sys/queue.h>

// our list element, with embedded links
struct elem {
    TAILQ_ENTRY(elem) _links;
    int datum;
    // ... other stuff goes here
};

// declare struct for a head of list of elem's
TAILQ_HEAD(list_of_elem, elem);

int main ()
{
    struct list_of_elem mylist;
    struct elem myelems[] = { {.datum = 3}, {.datum = 7}, {.datum = 1} };
    struct elem *pelem;

    TAILQ_INIT(&mylist);
    TAILQ_INSERT_HEAD(&mylist, &myelems[0], _links);
    TAILQ_INSERT_AFTER(&mylist, &myelems[0], &myelems[1], _links);
    TAILQ_INSERT_TAIL(&mylist, &myelems[2], _links);

    TAILQ_FOREACH(pelem, &mylist, _links) {
        printf(" %d", pelem->datum);
    }
    puts("");

    TAILQ_FOREACH_REVERSE(pelem, &mylist, list_of_elem, _links) {
        printf(" %d", pelem->datum);
    }
    puts("");

    while (!TAILQ_EMPTY(&mylist)) {
        pelem = TAILQ_FIRST(&mylist);
        TAILQ_REMOVE(&mylist, pelem, _links);
    }

    return 0;
}
Lalla answered 11/3, 2024 at 21:31 Comment(2)
These examples using BSD 'queue macros that are included within structs can be efficient,but external functions to refer to arbitrary elements are often preferable.Lalla
I don't really agree this is more readable and didactic, but I support your desire to express your point of view. Upvoted.Grizelda

© 2022 - 2025 — McMap. All rights reserved.