list_for_each_entry
Rev.4を表示中。最新版はこちら。
[root@localhost north]# cat sample.c#include <stddef.h> #include <stdio.h> struct list_head { struct list_head *next, *prev; }; struct babakaka1 { struct list_head child; struct list_head parent; int data; }; struct babakaka2 { int data; struct list_head child; struct list_head parent; }; struct babakaka1 a1,b1,c1,d1; struct babakaka2 a2,b2,c2,d2; void obj1_list(); void obj1_disp(); void obj2_list(); void obj2_disp(); void main() { obj1_list(); obj2_list();
obj1_disp(); obj2_disp(); } void obj1_list() { a1.data = 1; b1.data = 2; c1.data = 3; d1.data = 4; a1.parent.next = &b1.child; b1.child.next = &c1.child; c1.child.next = &d1.child; d1.child.next = &a1.parent; } void obj2_list() { a2.data = 1; b2.data = 2; c2.data = 3; d2.data = 4; a2.parent.next = &b2.child; b2.child.next = &c2.child; c2.child.next = &d2.child; d2.child.next = &a2.parent; } void obj1_disp() { struct babakaka1 *obj; int offset_child; printf("***disp obj[1]\n"); offset_child = offsetof(struct babakaka1, child); printf("listed child member offset in struct:%d\n", offset_child); obj = &a1; printf("%d\n", obj->data); obj = (struct babakaka1 *)obj->parent.next; while(1) { printf("%d\n", obj->data); if(obj->child.next == &a1.parent) { break; } obj = (struct babakaka1 *)obj->child.next; } } void obj2_disp() { struct babakaka2 *obj, *obj1; int offset_child; printf("***disp obj[2]\n"); offset_child = offsetof(struct babakaka2, child); printf("listed child offset member in struct:%d\n", offset_child); obj = &a2; printf("%d\n", obj->data); obj = (struct babakaka2 *)((char *)obj->parent.next - offset_child); while(1) { printf("%d\n", obj->data); if(obj->child.next == &a2.parent) { break; } obj = (struct babakaka2 *)((char *)obj->child.next - offset_child); } }
[root@localhost north]# ./sample.out ***disp obj[1] listed child member offset in struct:0 1 2 3 4 ***disp obj[2] listed child offset member in struct:4 1 2 3 4
list_for_each_entryは、disp obj[2]に係る処理のマクロによるfor文による実装
#define list_for_each_entry(pos, head, member) \ for (pos = list_entry((head)->next, typeof(*pos), member); \ &pos->member != (head); \ pos = list_entry(pos->member.next, typeof(*pos), member)) #define list_for_each(pos, head) \ for (pos = (head)->next; pos != (head); pos = pos->next) #define list_entry(ptr, type, member) \ container_of(ptr, type, member)
#define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );})
備考
オブジェクトが複数のリストで管理するケースでは、struct list_head childに係るメンバーは複数設定される故、list_head childオフセットを考慮しないdisp obj[1]による実装されない。list_head->prevは接続元の親オブジェクトで、オブジェクト削除は、削除オブジェクト->prev->next = 削除オブジェクト->nextとなる。親オジェクトのprevは、リストされている終端オブジェクトで、オブジェクトの追加時に参照される。