1 /* 2 * safe_list - linked list protected against recursive iteration with deletes 3 * 4 * Copyright (C) 2013 Felix Fietkau <nbd@openwrt.org> 5 * 6 * Permission to use, copy, modify, and/or distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19 #include "safe_list.h" 20 21 struct safe_list_iterator { 22 struct safe_list_iterator **head; 23 struct safe_list_iterator *next_i; 24 struct safe_list *next; 25 }; 26 27 static void 28 __safe_list_set_iterator(struct safe_list *list, 29 struct safe_list_iterator *i) 30 { 31 struct safe_list_iterator *next_i; 32 struct safe_list *next; 33 34 next = list_entry(list->list.next, struct safe_list, list); 35 next_i = next->i; 36 37 next->i = i; 38 i->next = next; 39 i->head = &next->i; 40 41 i->next_i = next_i; 42 if (next_i) 43 next_i->head = &i->next_i; 44 } 45 46 static void 47 __safe_list_del_iterator(struct safe_list_iterator *i) 48 { 49 *i->head = i->next_i; 50 if (i->next_i) 51 i->next_i->head = i->head; 52 } 53 54 static void 55 __safe_list_move_iterator(struct safe_list *list, 56 struct safe_list_iterator *i) 57 { 58 __safe_list_del_iterator(i); 59 __safe_list_set_iterator(list, i); 60 } 61 62 int safe_list_for_each(struct safe_list *head, 63 int (*cb)(void *ctx, struct safe_list *list), 64 void *ctx) 65 { 66 struct safe_list_iterator i; 67 struct safe_list *cur; 68 int ret = 0; 69 70 for (cur = list_entry(head->list.next, struct safe_list, list), 71 __safe_list_set_iterator(cur, &i); 72 cur != head; 73 cur = i.next, __safe_list_move_iterator(cur, &i)) { 74 ret = cb(ctx, cur); 75 if (ret) 76 break; 77 } 78 79 __safe_list_del_iterator(&i); 80 return ret; 81 } 82 83 void safe_list_add(struct safe_list *list, struct safe_list *head) 84 { 85 list->i = NULL; 86 list_add_tail(&list->list, &head->list); 87 } 88 89 void safe_list_add_first(struct safe_list *list, struct safe_list *head) 90 { 91 list->i = NULL; 92 list_add(&list->list, &head->list); 93 } 94 95 void safe_list_del(struct safe_list *list) 96 { 97 struct safe_list_iterator *i, *next_i, **tail; 98 struct safe_list *next; 99 100 next = list_entry(list->list.next, struct safe_list, list); 101 list_del(&list->list); 102 103 if (!list->i) 104 return; 105 106 next_i = next->i; 107 tail = &next->i; 108 109 for (i = list->i; i; i = i->next_i) { 110 tail = &i->next_i; 111 i->next = next; 112 } 113 114 next->i = list->i; 115 list->i->head = &next->i; 116 *tail = next_i; 117 if (next_i) 118 next_i->head = tail; 119 120 list->i = NULL; 121 } 122
This page was automatically generated by LXR 0.3.1. • OpenWrt