Why are you not using GLib style lists?

Asked by Pavel Sterin

Hi!

In the source you are using doubly linked lists, where linked nodes are attached to an object which manages them (tail, offset and head). I am probably wrong, but the only benefit I can think of that construction, is that the tail pointer is always available. I do not know how often this pointer is actually used, so maybe i miss a point here.

Why not to use something like that (inspired by GList):
- a node pointing to NULL, is a perfect empty list
- the head of list _is_ the list
- additional to that: template-style-macros

#define list_foreach(_ty, _it, _li) \
 for(\
  _ty *(_it) = (_li),\
  *_next = (_li) ? (_li)->next : NULL;\
  (_it);\
  (_it) = _next,\
  _next = (_next) ? _next->next : NULL)

#define list_prepend(_ty, _li, _no, _err) \
 do {\
  if (_li && _no) {\
   (_err) = 0;\
   (_no)->next = (_li);\
   (_no)->prev = NULL;\
   (_li)->prev = (_no);\
   (_li) = (_no);\
  } else if (_no && !(_li)) {\
   (_err) = 0;\
   (_no)->prev = NULL;\
   (_no)->next = NULL;\
   (_li) = (_no);\
  } else {\
   (_err) = EINVAL;\
  }\
 } while(0)

struct container {
 struct container *prev;
 struct container *next;
 int foo;
}

struct box {
 struct container *prev;
 struct container *next;
 float bar;
}

struct box *node;

list_foreach(struct container, it, list) {
 printf("foo number %d\n", it->foo);
 if (it == node) {...} /* this produces an unambiguous warning */
}

list_prepend(struct container, list, node, err); /* again warning*/

struct container *cnode;

list_prepend(struct container, list, cnode, err); /* pass */
if (err != 0)
 return_error(err);

The benefit of my solution is, that there is no possibility of accidentally inserting a node of wrong type into the list, because the pointer has always the type of the node.
(variable declaration is in the for clause, because the project already uses -std=c99, or am I wrong?).

regards,
Pavel

Question information

Language:
English Edit question
Status:
Answered
For:
libbls Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Launchpad Janitor (janitor) said :
#1

This question was expired because it remained in the 'Open' state without activity for the last 15 days.

Revision history for this message
Alexandros Frantzis (afrantzis) said :
#2

Have been busy.

Revision history for this message
Alexandros Frantzis (afrantzis) said :
#3

Hi Pavel,

the main reason for doing things as they are is to be able to have a pointer to the tail node.
The tail node is needed so that reverse traversal can be done efficiently and also for appending
to the list efficiently.

As for type safety, your solution is indeed better. However, I haven't found this to be a practical issue.
Furthermore my choices (using an abstract list_node) were dictated by my preference to use functions
instead of macros when I can (your method requires macros for list operations)

Regards,
Alexandros

Can you help with this problem?

Provide an answer of your own, or ask Pavel Sterin for more information if necessary.

To post a message you must log in.