Use linux kernel function 'list_for_each_entry()' in Visual C++
ProgrammingThis forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
Use linux kernel function 'list_for_each_entry()' in Visual C++
Hello everyone,
I am trying to use Linux's implementation of 'list' in Visual C++ 2005.
The following is the 'list.h' code ( I replace 'typeof' with 'typeid' ) :
Code:
#ifndef __LIST_H
#define __LIST_H
/* This file is from Linux Kernel (include/linux/list.h)
* and modified by simply removing hardware prefetching of list items.
* Here by copyright, credits attributed to wherever they belong.
* Kulesh Shanmugasundaram (kulesh [squiggly] isis.poly.edu)
*/
/*
* Simple doubly linked list implementation.
*
* Some of the internal functions ("__xxx") are useful when
* manipulating whole lists rather than single entries, as
* sometimes we already know the next/prev entries and we can
* generate better code by using them directly rather than
* using the generic single-entry routines.
*/
struct list_head {
struct list_head *next, *prev;
};
#define LIST_HEAD_INIT(name) { &(name), &(name) }
#define LIST_HEAD(name) \
struct list_head name = LIST_HEAD_INIT(name)
#define INIT_LIST_HEAD(ptr) do { \
(ptr)->next = (ptr); (ptr)->prev = (ptr); \
} while (0)
/*
* Insert a new entry between two known consecutive entries.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_add(struct list_head *new_element,
struct list_head *prev,
struct list_head *next)
{
next->prev = new_element;
new_element->next = next;
new_element->prev = prev;
prev->next = new_element;
}
/**
* list_add - add a new entry
* @new: new entry to be added
* @head: list head to add it after
*
* Insert a new entry after the specified head.
* This is good for implementing stacks.
*/
static inline void list_add(struct list_head *new_element, struct list_head *head)
{
__list_add(new_element, head, head->next);
}
/**
* list_add_tail - add a new entry
* @new: new entry to be added
* @head: list head to add it before
*
* Insert a new entry before the specified head.
* This is useful for implementing queues.
*/
static inline void list_add_tail(struct list_head *new_element, struct list_head *head)
{
__list_add(new_element, head->prev, head);
}
/*
* Delete a list entry by making the prev/next entries
* point to each other.
*
* This is only for internal list manipulation where we know
* the prev/next entries already!
*/
static inline void __list_del(struct list_head *prev, struct list_head *next)
{
next->prev = prev;
prev->next = next;
}
/**
* list_del - deletes entry from list.
* @entry: the element to delete from the list.
* Note: list_empty on entry does not return true after this, the entry is in an undefined state.
*/
static inline void list_del(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
entry->next = (list_head *) 0;
entry->prev = (list_head *) 0;
}
/**
* list_del_init - deletes entry from list and reinitialize it.
* @entry: the element to delete from the list.
*/
static inline void list_del_init(struct list_head *entry)
{
__list_del(entry->prev, entry->next);
INIT_LIST_HEAD(entry);
}
/**
* list_move - delete from one list and add as another's head
* @list: the entry to move
* @head: the head that will precede our entry
*/
static inline void list_move(struct list_head *list, struct list_head *head)
{
__list_del(list->prev, list->next);
list_add(list, head);
}
/**
* list_move_tail - delete from one list and add as another's tail
* @list: the entry to move
* @head: the head that will follow our entry
*/
static inline void list_move_tail(struct list_head *list,
struct list_head *head)
{
__list_del(list->prev, list->next);
list_add_tail(list, head);
}
/**
* list_empty - tests whether a list is empty
* @head: the list to test.
*/
static inline int list_empty(struct list_head *head)
{
return head->next == head;
}
static inline void __list_splice(struct list_head *list,
struct list_head *head)
{
struct list_head *first = list->next;
struct list_head *last = list->prev;
struct list_head *at = head->next;
first->prev = head;
head->next = first;
last->next = at;
at->prev = last;
}
/**
* list_splice - join two lists
* @list: the new list to add.
* @head: the place to add it in the first list.
*/
static inline void list_splice(struct list_head *list, struct list_head *head)
{
if (!list_empty(list))
__list_splice(list, head);
}
/**
* list_splice_init - join two lists and reinitialise the emptied list.
* @list: the new list to add.
* @head: the place to add it in the first list.
*
* The list at @list is reinitialised
*/
static inline void list_splice_init(struct list_head *list,
struct list_head *head)
{
if (!list_empty(list)) {
__list_splice(list, head);
INIT_LIST_HEAD(list);
}
}
/**
* list_entry - get the struct for this entry
* @ptr: the &struct list_head pointer.
* @type: the type of the struct this is embedded in.
* @member: the name of the list_struct within the struct.
*/
#define list_entry(ptr, type, member) \
((type *)((char *)(ptr)-(unsigned long)(&((type *)0)->member)))
/**
* list_for_each - iterate over a list
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each(pos, head) \
for (pos = (head)->next; pos != (head); \
pos = pos->next)
/**
* list_for_each_prev - iterate over a list backwards
* @pos: the &struct list_head to use as a loop counter.
* @head: the head for your list.
*/
#define list_for_each_prev(pos, head) \
for (pos = (head)->prev; pos != (head); \
pos = pos->prev)
/**
* list_for_each_safe - iterate over a list safe against removal of list entry
* @pos: the &struct list_head to use as a loop counter.
* @n: another &struct list_head to use as temporary storage
* @head: the head for your list.
*/
#define list_for_each_safe(pos, n, head) \
for (pos = (head)->next, n = pos->next; pos != (head); \
pos = n, n = pos->next)
/**
* list_for_each_entry - iterate over list of given type
* @pos: the type * to use as a loop counter.
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry(pos, head, member) \
for (pos = list_entry((head)->next, typeid(*pos), member); \
&pos->member != (head); \
pos = list_entry(pos->member.next, typeid(*pos), member))
/**
* list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
* @pos: the type * to use as a loop counter.
* @n: another type * to use as temporary storage
* @head: the head for your list.
* @member: the name of the list_struct within the struct.
*/
#define list_for_each_entry_safe(pos, n, head, member) \
for (pos = list_entry((head)->next, typeid(*pos), member), \
n = list_entry(pos->member.next, typeid(*pos), member); \
&pos->member != (head); \
pos = n, n = list_entry(n->member.next, typeid(*n), member))
#endif
The following is a sample code from internet that works in Linux:
Code:
#include <stdio.h>
#include <stdlib.h>
#include "list.h"
struct kool_list{
int to;
struct list_head list;
int from;
};
int main(int argc, char **argv){
struct kool_list *tmp;
struct list_head *pos, *q;
unsigned int i;
struct kool_list mylist;
INIT_LIST_HEAD(&mylist.list);
for(i=5; i!=0; --i){
tmp= (struct kool_list *)malloc(sizeof(struct kool_list));
printf("enter to and from:");
scanf("%d %d", &tmp->to, &tmp->from);
/* add the new item 'tmp' to the list of items in mylist */
list_add(&(tmp->list), &(mylist.list));
}
printf("\n");
printf("traversing the list using list_for_each()\n");
list_for_each(pos, &mylist.list){
tmp= list_entry(pos, struct kool_list, list);
printf("to= %d from= %d\n", tmp->to, tmp->from);
}
printf("\n");
printf("traversing the list using list_for_each_entry()\n");
list_for_each_entry(tmp, &mylist.list, list)
printf("to= %d from= %d\n", tmp->to, tmp->from);
printf("\n");
printf("deleting the list using list_for_each_safe()\n");
list_for_each_safe(pos, q, &mylist.list){
tmp= list_entry(pos, struct kool_list, list);
printf("freeing item to= %d from= %d\n", tmp->to, tmp->from);
list_del(pos);
free(tmp);
}
return 0;
}
in Visual Studio 2005, when compiling it reminds me missing ';' after 'list_for_each_entry(tmp, &mylist.list, list)'.
Even if 'typeid' might not a good replacement of 'typeof' here, I though it should compile successfully anyway yet it wasn't.
I see you’ve already made two posts about this same problem. Why start a third, when you can just add on to a previous one?
Quote:
Originally Posted by Kunsheng
Even if 'typeid' might not a good replacement of 'typeof' here, I though it should compile successfully anyway yet it wasn't.
Why would you think so when it has already been pointed out that they are completely different constructs and things will break if you simply substitute one for the other?
Quote:
Originally Posted by Kunsheng
Does anyone have some idea ?
Yes, as has been said time and again, use C++. Additionally, you have been given a MSVC-specific solution as well, but have failed to use it. Btw, you have many ways to traverse lists in C++:
Code:
#include <list>
#include <iostream>
#include <algorithm>
#include <boost/foreach.hpp>
using std::list;
using std::cout;
using std::cin;
using std::for_each;
struct kool_list {
int to;
int from;
};
inline void print(kool_list &t) {
cout << "to = " << t.to << " from = " << t.from << "\n";
}
int main(int argc, char *argv[]) {
list<kool_list> mylist;
for (int i = 5; i != 0; --i) {
kool_list tmp;
cout << "enter to and from: ";
cin >> tmp.to >> tmp.from;
mylist.push_back(tmp);
}
cout << "Traversing list with iterators\n";
for (list<kool_list>::iterator i = mylist.begin(); i != mylist.end(); i++)
cout << "to = " << i->to << " from = " << i->from << "\n";
cout << "Traversing list with std::for_each\n";
for_each(mylist.begin(), mylist.end(), print);
cout << "Traversing list through BOOST_FOREACH\n";
BOOST_FOREACH(kool_list t, mylist)
cout << "to = " << t.to << " from = " << t.from << "\n";
cout << "Deleting the entire list at once using list.clear()\n";
mylist.clear();
return 0;
}
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.