zoukankan      html  css  js  c++  java
  • linux内核数据结构之链表-实现

    代码:list.h

      1 /*
      2  * @file list.h
      3  * @author PF
      4  * @date 2017/05/1
      5  *
      6  * port from linux kernel list.h: https://github.com/torvalds/linux/raw/master/include/linux/list.h
      7  *
      8  * Here is a recipe to cook list.h for user space program.
      9  * 1. copy list.h from linux/include/list.h
     10  * 2. remove
     11  *     - #ifdef __KERNE__ and its #endif
     12  *     - all #include line
     13  *     - prefetch() and rcu related functions
     14  * 3. add macro offsetof() and container_of
     15  */
     16 
     17 #ifndef LIST_H_
     18 #define LIST_H_ (1)
     19 
     20 // import from include/linux/types.h
     21 struct list_head {
     22     struct list_head *next, *prev;
     23 };
     24 
     25 struct hlist_head {
     26     struct hlist_node *first;
     27 };
     28 
     29 struct hlist_node {
     30     struct hlist_node *next, **pprev;
     31 };
     32 
     33 // import from include/linux/poison.h
     34 
     35 /*
     36  * Architectures might want to move the poison pointer offset
     37  * into some well-recognized area such as 0xdead000000000000,
     38  * that is also not mappable by user-space exploits:
     39  */
     40 #ifdef CONFIG_ILLEGAL_POINTER_VALUE
     41 # define POISON_POINTER_DELTA _AC(CONFIG_ILLEGAL_POINTER_VALUE, UL)
     42 #else
     43 # define POISON_POINTER_DELTA (0)
     44 #endif
     45 
     46 /*
     47  * These are non-NULL pointers that will result in page faults
     48  * under normal circumstances, used to verify that nobody uses
     49  * non-initialized list entries.
     50  */
     51 #define LIST_POISON1  ((void *) 0x00100100 + POISON_POINTER_DELTA)
     52 #define LIST_POISON2  ((void *) 0x00200200 + POISON_POINTER_DELTA)
     53 
     54 // import from include/linux/stddef.h
     55 #undef offsetof
     56 #ifdef __compiler_offsetof
     57 #define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
     58 #else
     59 #define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
     60 #endif
     61 
     62 // import from include/linux/kernel.h
     63 /**
     64 * container_of - cast a member of a structure out to the containing structure
     65 * @ptr:        the pointer to the member.
     66 * @type:       the type of the container struct this is embedded in.
     67 * @member:     the name of the member within the struct.
     68 *
     69 */
     70 #define container_of(ptr, type, member) ({                      
     71         const typeof( ((type *)0)->member ) *__mptr = (ptr);    
     72         (type *)( (char *)__mptr - offsetof(type,member) );})
     73 
     74 /*
     75  * Simple doubly linked list implementation.
     76  *
     77  * Some of the internal functions ("__xxx") are useful when
     78  * manipulating whole lists rather than single entries, as
     79  * sometimes we already know the next/prev entries and we can
     80  * generate better code by using them directly rather than
     81  * using the generic single-entry routines.
     82  */
     83 
     84 #define LIST_HEAD_INIT(name) { &(name), &(name) }
     85 
     86 #define LIST_HEAD(name) 
     87     struct list_head name = LIST_HEAD_INIT(name)
     88 
     89 static inline void INIT_LIST_HEAD(struct list_head *list) {
     90     list->next = list;
     91     list->prev = list;
     92 }
     93 
     94 /*
     95  * Insert a new entry between two known consecutive entries.
     96  *
     97  * This is only for internal list manipulation where we know
     98  * the prev/next entries already!
     99  */
    100 #ifndef CONFIG_DEBUG_LIST
    101 static inline void __list_add(struct list_head *new,
    102     struct list_head *prev,
    103     struct list_head *next) {
    104     next->prev = new;
    105     new->next = next;
    106     new->prev = prev;
    107     prev->next = new;
    108 }
    109 #else
    110 extern void __list_add(struct list_head *new,
    111                   struct list_head *prev,
    112                   struct list_head *next);
    113 #endif
    114 
    115 /**
    116  * list_add - add a new entry
    117  * @new: new entry to be added
    118  * @head: list head to add it after
    119  *
    120  * Insert a new entry after the specified head.
    121  * This is good for implementing stacks.
    122  */
    123 static inline void list_add(struct list_head *new, struct list_head *head) {
    124     __list_add(new, head, head->next);
    125 }
    126 
    127 /**
    128  * list_add_tail - add a new entry
    129  * @new: new entry to be added
    130  * @head: list head to add it before
    131  *
    132  * Insert a new entry before the specified head.
    133  * This is useful for implementing queues.
    134  */
    135 static inline void list_add_tail(struct list_head *new, struct list_head *head) {
    136     __list_add(new, head->prev, head);
    137 }
    138 
    139 /*
    140  * Delete a list entry by making the prev/next entries
    141  * point to each other.
    142  *
    143  * This is only for internal list manipulation where we know
    144  * the prev/next entries already!
    145  */
    146 static inline void __list_del(struct list_head *prev, struct list_head *next) {
    147     next->prev = prev;
    148     prev->next = next;
    149 }
    150 
    151 /**
    152  * list_del - deletes entry from list.
    153  * @entry: the element to delete from the list.
    154  * Note: list_empty() on entry does not return true after this, the entry is
    155  * in an undefined state.
    156  */
    157 #ifndef CONFIG_DEBUG_LIST
    158 
    159 static inline void __list_del_entry(struct list_head *entry) {
    160     __list_del(entry->prev, entry->next);
    161 }
    162 
    163 static inline void list_del(struct list_head *entry) {
    164     __list_del(entry->prev, entry->next);
    165     entry->next = LIST_POISON1;
    166     entry->prev = LIST_POISON2;
    167 }
    168 
    169 #else
    170 extern void __list_del_entry(struct list_head *entry);
    171 extern void list_del(struct list_head *entry);
    172 #endif
    173 
    174 /**
    175  * list_replace - replace old entry by new one
    176  * @old : the element to be replaced
    177  * @new : the new element to insert
    178  *
    179  * If @old was empty, it will be overwritten.
    180  */
    181 static inline void list_replace(struct list_head *old,
    182         struct list_head *new) {
    183     new->next = old->next;
    184     new->next->prev = new;
    185     new->prev = old->prev;
    186     new->prev->next = new;
    187 }
    188 
    189 static inline void list_replace_init(struct list_head *old,
    190         struct list_head *new) {
    191     list_replace(old, new);
    192     INIT_LIST_HEAD(old);
    193 }
    194 
    195 /**
    196  * list_del_init - deletes entry from list and reinitialize it.
    197  * @entry: the element to delete from the list.
    198  */
    199 static inline void list_del_init(struct list_head *entry) {
    200     __list_del_entry(entry);
    201     INIT_LIST_HEAD(entry);
    202 }
    203 
    204 /**
    205  * list_move - delete from one list and add as another's head
    206  * @list: the entry to move
    207  * @head: the head that will precede our entry
    208  */
    209 static inline void list_move(struct list_head *list, struct list_head *head) {
    210     __list_del_entry(list);
    211     list_add(list, head);
    212 }
    213 
    214 /**
    215  * list_move_tail - delete from one list and add as another's tail
    216  * @list: the entry to move
    217  * @head: the head that will follow our entry
    218  */
    219 static inline void list_move_tail(struct list_head *list,
    220         struct list_head *head) {
    221     __list_del_entry(list);
    222     list_add_tail(list, head);
    223 }
    224 
    225 /**
    226  * list_is_last - tests whether @list is the last entry in list @head
    227  * @list: the entry to test
    228  * @head: the head of the list
    229  */
    230 static inline int list_is_last(const struct list_head *list,
    231         const struct list_head *head) {
    232     return list->next == head;
    233 }
    234 
    235 /**
    236  * list_empty - tests whether a list is empty
    237  * @head: the list to test.
    238  */
    239 static inline int list_empty(const struct list_head *head) {
    240     return head->next == head;
    241 }
    242 
    243 /**
    244  * list_empty_careful - tests whether a list is empty and not being modified
    245  * @head: the list to test
    246  *
    247  * Description:
    248  * tests whether a list is empty _and_ checks that no other CPU might be
    249  * in the process of modifying either member (next or prev)
    250  *
    251  * NOTE: using list_empty_careful() without synchronization
    252  * can only be safe if the only activity that can happen
    253  * to the list entry is list_del_init(). Eg. it cannot be used
    254  * if another CPU could re-list_add() it.
    255  */
    256 static inline int list_empty_careful(const struct list_head *head) {
    257     struct list_head *next = head->next;
    258     return (next == head) && (next == head->prev);
    259 }
    260 
    261 /**
    262  * list_rotate_left - rotate the list to the left
    263  * @head: the head of the list
    264  */
    265 static inline void list_rotate_left(struct list_head *head) {
    266     struct list_head *first;
    267 
    268     if (!list_empty(head)) {
    269         first = head->next;
    270         list_move_tail(first, head);
    271     }
    272 }
    273 
    274 /**
    275  * list_is_singular - tests whether a list has just one entry.
    276  * @head: the list to test.
    277  */
    278 static inline int list_is_singular(const struct list_head *head) {
    279     return !list_empty(head) && (head->next == head->prev);
    280 }
    281 
    282 static inline void __list_cut_position(struct list_head *list,
    283         struct list_head *head, struct list_head *entry) {
    284     struct list_head *new_first = entry->next;
    285     list->next = head->next;
    286     list->next->prev = list;
    287     list->prev = entry;
    288     entry->next = list;
    289     head->next = new_first;
    290     new_first->prev = head;
    291 }
    292 
    293 /**
    294  * list_cut_position - cut a list into two
    295  * @list: a new list to add all removed entries
    296  * @head: a list with entries
    297  * @entry: an entry within head, could be the head itself
    298  *  and if so we won't cut the list
    299  *
    300  * This helper moves the initial part of @head, up to and
    301  * including @entry, from @head to @list. You should
    302  * pass on @entry an element you know is on @head. @list
    303  * should be an empty list or a list you do not care about
    304  * losing its data.
    305  *
    306  */
    307 static inline void list_cut_position(struct list_head *list,
    308         struct list_head *head, struct list_head *entry) {
    309     if (list_empty(head)) {
    310         return;
    311     }
    312     if (list_is_singular(head) &&
    313             (head->next != entry && head != entry)) {
    314         return;
    315     }
    316     if (entry == head) {
    317         INIT_LIST_HEAD(list);
    318     } else {
    319         __list_cut_position(list, head, entry);
    320     }
    321 }
    322 
    323 static inline void __list_splice(const struct list_head *list,
    324         struct list_head *prev,
    325         struct list_head *next) {
    326     struct list_head *first = list->next;
    327     struct list_head *last = list->prev;
    328 
    329     first->prev = prev;
    330     prev->next = first;
    331 
    332     last->next = next;
    333     next->prev = last;
    334 }
    335 
    336 /**
    337  * list_splice - join two lists, this is designed for stacks
    338  * @list: the new list to add.
    339  * @head: the place to add it in the first list.
    340  */
    341 static inline void list_splice(const struct list_head *list,
    342         struct list_head *head) {
    343     if (!list_empty(list)) {
    344         __list_splice(list, head, head->next);
    345     }
    346 }
    347 
    348 /**
    349  * list_splice_tail - join two lists, each list being a queue
    350  * @list: the new list to add.
    351  * @head: the place to add it in the first list.
    352  */
    353 static inline void list_splice_tail(struct list_head *list,
    354         struct list_head *head) {
    355     if (!list_empty(list)) {
    356         __list_splice(list, head->prev, head);
    357     }
    358 }
    359 
    360 /**
    361  * list_splice_init - join two lists and reinitialise the emptied list.
    362  * @list: the new list to add.
    363  * @head: the place to add it in the first list.
    364  *
    365  * The list at @list is reinitialised
    366  */
    367 static inline void list_splice_init(struct list_head *list,
    368         struct list_head *head) {
    369     if (!list_empty(list)) {
    370         __list_splice(list, head, head->next);
    371         INIT_LIST_HEAD(list);
    372     }
    373 }
    374 
    375 /**
    376  * list_splice_tail_init - join two lists and reinitialise the emptied list
    377  * @list: the new list to add.
    378  * @head: the place to add it in the first list.
    379  *
    380  * Each of the lists is a queue.
    381  * The list at @list is reinitialised
    382  */
    383 static inline void list_splice_tail_init(struct list_head *list,
    384         struct list_head *head) {
    385     if (!list_empty(list)) {
    386         __list_splice(list, head->prev, head);
    387         INIT_LIST_HEAD(list);
    388     }
    389 }
    390 
    391 /**
    392  * list_entry - get the struct for this entry
    393  * @ptr:    the &struct list_head pointer.
    394  * @type:   the type of the struct this is embedded in.
    395  * @member: the name of the list_head within the struct.
    396  */
    397 #define list_entry(ptr, type, member) 
    398     container_of(ptr, type, member)
    399 
    400 /**
    401  * list_first_entry - get the first element from a list
    402  * @ptr:    the list head to take the element from.
    403  * @type:   the type of the struct this is embedded in.
    404  * @member: the name of the list_head within the struct.
    405  *
    406  * Note, that list is expected to be not empty.
    407  */
    408 #define list_first_entry(ptr, type, member) 
    409     list_entry((ptr)->next, type, member)
    410 
    411 /**
    412  * list_last_entry - get the last element from a list
    413  * @ptr:    the list head to take the element from.
    414  * @type:   the type of the struct this is embedded in.
    415  * @member: the name of the list_head within the struct.
    416  *
    417  * Note, that list is expected to be not empty.
    418  */
    419 #define list_last_entry(ptr, type, member) 
    420     list_entry((ptr)->prev, type, member)
    421 
    422 /**
    423  * list_first_entry_or_null - get the first element from a list
    424  * @ptr:    the list head to take the element from.
    425  * @type:   the type of the struct this is embedded in.
    426  * @member: the name of the list_head within the struct.
    427  *
    428  * Note that if the list is empty, it returns NULL.
    429  */
    430 #define list_first_entry_or_null(ptr, type, member) 
    431     (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
    432 
    433 /**
    434  * list_next_entry - get the next element in list
    435  * @pos:    the type * to cursor
    436  * @member: the name of the list_head within the struct.
    437  */
    438 #define list_next_entry(pos, member) 
    439     list_entry((pos)->member.next, typeof(*(pos)), member)
    440 
    441 /**
    442  * list_prev_entry - get the prev element in list
    443  * @pos:    the type * to cursor
    444  * @member: the name of the list_head within the struct.
    445  */
    446 #define list_prev_entry(pos, member) 
    447     list_entry((pos)->member.prev, typeof(*(pos)), member)
    448 
    449 /**
    450  * list_for_each    -   iterate over a list
    451  * @pos:    the &struct list_head to use as a loop cursor.
    452  * @head:   the head for your list.
    453  */
    454 #define list_for_each(pos, head) 
    455     for (pos = (head)->next; pos != (head); pos = pos->next)
    456 
    457 /**
    458  * list_for_each_prev   -   iterate over a list backwards
    459  * @pos:    the &struct list_head to use as a loop cursor.
    460  * @head:   the head for your list.
    461  */
    462 #define list_for_each_prev(pos, head) 
    463     for (pos = (head)->prev; pos != (head); pos = pos->prev)
    464 
    465 /**
    466  * list_for_each_safe - iterate over a list safe against removal of list entry
    467  * @pos:    the &struct list_head to use as a loop cursor.
    468  * @n:      another &struct list_head to use as temporary storage
    469  * @head:   the head for your list.
    470  */
    471 #define list_for_each_safe(pos, n, head) 
    472     for (pos = (head)->next, n = pos->next; pos != (head); 
    473         pos = n, n = pos->next)
    474 
    475 /**
    476  * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry
    477  * @pos:    the &struct list_head to use as a loop cursor.
    478  * @n:      another &struct list_head to use as temporary storage
    479  * @head:   the head for your list.
    480  */
    481 #define list_for_each_prev_safe(pos, n, head) 
    482     for (pos = (head)->prev, n = pos->prev; 
    483          pos != (head); 
    484          pos = n, n = pos->prev)
    485 
    486 /**
    487  * list_for_each_entry  -   iterate over list of given type
    488  * @pos:    the type * to use as a loop cursor.
    489  * @head:   the head for your list.
    490  * @member: the name of the list_head within the struct.
    491  */
    492 #define list_for_each_entry(pos, head, member)                
    493     for (pos = list_first_entry(head, typeof(*pos), member);    
    494          &pos->member != (head);                    
    495          pos = list_next_entry(pos, member))
    496 
    497 /**
    498  * list_for_each_entry_reverse - iterate backwards over list of given type.
    499  * @pos:    the type * to use as a loop cursor.
    500  * @head:   the head for your list.
    501  * @member: the name of the list_head within the struct.
    502  */
    503 #define list_for_each_entry_reverse(pos, head, member)            
    504     for (pos = list_last_entry(head, typeof(*pos), member);        
    505          &pos->member != (head);                    
    506          pos = list_prev_entry(pos, member))
    507 
    508 /**
    509  * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue()
    510  * @pos:    the type * to use as a start point
    511  * @head:   the head of the list
    512  * @member: the name of the list_head within the struct.
    513  *
    514  * Prepares a pos entry for use as a start point in list_for_each_entry_continue().
    515  */
    516 #define list_prepare_entry(pos, head, member) 
    517     ((pos) ? : list_entry(head, typeof(*pos), member))
    518 
    519 /**
    520  * list_for_each_entry_continue - continue iteration over list of given type
    521  * @pos:    the type * to use as a loop cursor.
    522  * @head:   the head for your list.
    523  * @member: the name of the list_head within the struct.
    524  *
    525  * Continue to iterate over list of given type, continuing after
    526  * the current position.
    527  */
    528 #define list_for_each_entry_continue(pos, head, member)        
    529     for (pos = list_next_entry(pos, member);            
    530          &pos->member != (head);                    
    531          pos = list_next_entry(pos, member))
    532 
    533 /**
    534  * list_for_each_entry_continue_reverse - iterate backwards from the given point
    535  * @pos:    the type * to use as a loop cursor.
    536  * @head:   the head for your list.
    537  * @member: the name of the list_head within the struct.
    538  *
    539  * Start to iterate over list of given type backwards, continuing after
    540  * the current position.
    541  */
    542 #define list_for_each_entry_continue_reverse(pos, head, member)        
    543     for (pos = list_prev_entry(pos, member);            
    544          &pos->member != (head);                    
    545          pos = list_prev_entry(pos, member))
    546 
    547 /**
    548  * list_for_each_entry_from - iterate over list of given type from the current point
    549  * @pos:    the type * to use as a loop cursor.
    550  * @head:   the head for your list.
    551  * @member: the name of the list_head within the struct.
    552  *
    553  * Iterate over list of given type, continuing from current position.
    554  */
    555 #define list_for_each_entry_from(pos, head, member)            
    556     for (; &pos->member != (head);                    
    557          pos = list_next_entry(pos, member))
    558 
    559 /**
    560  * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry
    561  * @pos:    the type * to use as a loop cursor.
    562  * @n:      another type * to use as temporary storage
    563  * @head:   the head for your list.
    564  * @member: the name of the list_head within the struct.
    565  */
    566 #define list_for_each_entry_safe(pos, n, head, member)            
    567     for (pos = list_first_entry(head, typeof(*pos), member),    
    568         n = list_next_entry(pos, member);            
    569          &pos->member != (head);                    
    570          pos = n, n = list_next_entry(n, member))
    571 
    572 /**
    573  * list_for_each_entry_safe_continue - continue list iteration safe against removal
    574  * @pos:    the type * to use as a loop cursor.
    575  * @n:      another type * to use as temporary storage
    576  * @head:   the head for your list.
    577  * @member: the name of the list_head within the struct.
    578  *
    579  * Iterate over list of given type, continuing after current point,
    580  * safe against removal of list entry.
    581  */
    582 #define list_for_each_entry_safe_continue(pos, n, head, member)        
    583     for (pos = list_next_entry(pos, member),                
    584         n = list_next_entry(pos, member);                
    585          &pos->member != (head);                        
    586          pos = n, n = list_next_entry(n, member))
    587 
    588 /**
    589  * list_for_each_entry_safe_from - iterate over list from current point safe against removal
    590  * @pos:    the type * to use as a loop cursor.
    591  * @n:      another type * to use as temporary storage
    592  * @head:   the head for your list.
    593  * @member: the name of the list_head within the struct.
    594  *
    595  * Iterate over list of given type from current point, safe against
    596  * removal of list entry.
    597  */
    598 #define list_for_each_entry_safe_from(pos, n, head, member)            
    599     for (n = list_next_entry(pos, member);                    
    600          &pos->member != (head);                        
    601          pos = n, n = list_next_entry(n, member))
    602 
    603 /**
    604  * list_for_each_entry_safe_reverse - iterate backwards over list safe against removal
    605  * @pos:    the type * to use as a loop cursor.
    606  * @n:      another type * to use as temporary storage
    607  * @head:   the head for your list.
    608  * @member: the name of the list_head within the struct.
    609  *
    610  * Iterate backwards over list of given type, safe against removal
    611  * of list entry.
    612  */
    613 #define list_for_each_entry_safe_reverse(pos, n, head, member)        
    614     for (pos = list_last_entry(head, typeof(*pos), member),        
    615         n = list_prev_entry(pos, member);            
    616          &pos->member != (head);                    
    617          pos = n, n = list_prev_entry(n, member))
    618 
    619 /**
    620  * list_safe_reset_next - reset a stale list_for_each_entry_safe loop
    621  * @pos:    the loop cursor used in the list_for_each_entry_safe loop
    622  * @n:      temporary storage used in list_for_each_entry_safe
    623  * @member: the name of the list_head within the struct.
    624  *
    625  * list_safe_reset_next is not safe to use in general if the list may be
    626  * modified concurrently (eg. the lock is dropped in the loop body). An
    627  * exception to this is if the cursor element (pos) is pinned in the list,
    628  * and list_safe_reset_next is called after re-taking the lock and before
    629  * completing the current iteration of the loop body.
    630  */
    631 #define list_safe_reset_next(pos, n, member)                
    632     n = list_next_entry(pos, member)
    633 
    634 /*
    635  * Double linked lists with a single pointer list head.
    636  * Mostly useful for hash tables where the two pointer list head is
    637  * too wasteful.
    638  * You lose the ability to access the tail in O(1).
    639  */
    640 
    641 #define HLIST_HEAD_INIT { .first = NULL }
    642 #define HLIST_HEAD(name) struct hlist_head name = {  .first = NULL }
    643 #define INIT_HLIST_HEAD(ptr) ((ptr)->first = NULL)
    644 
    645 static inline void INIT_HLIST_NODE(struct hlist_node *h) {
    646     h->next = NULL;
    647     h->pprev = NULL;
    648 }
    649 
    650 static inline int hlist_unhashed(const struct hlist_node *h) {
    651     return !h->pprev;
    652 }
    653 
    654 static inline int hlist_empty(const struct hlist_head *h) {
    655     return !h->first;
    656 }
    657 
    658 static inline void __hlist_del(struct hlist_node *n) {
    659     struct hlist_node *next = n->next;
    660     struct hlist_node **pprev = n->pprev;
    661     *pprev = next;
    662     if (next)
    663         next->pprev = pprev;
    664 }
    665 
    666 static inline void hlist_del(struct hlist_node *n) {
    667     __hlist_del(n);
    668     n->next = LIST_POISON1;
    669     n->pprev = LIST_POISON2;
    670 }
    671 
    672 static inline void hlist_del_init(struct hlist_node *n) {
    673     if (!hlist_unhashed(n)) {
    674         __hlist_del(n);
    675         INIT_HLIST_NODE(n);
    676     }
    677 }
    678 
    679 static inline void hlist_add_head(struct hlist_node *n, struct hlist_head *h) {
    680     struct hlist_node *first = h->first;
    681     n->next = first;
    682     if (first) {
    683         first->pprev = &n->next;
    684     }
    685     h->first = n;
    686     n->pprev = &h->first;
    687 }
    688 
    689 /* next must be != NULL */
    690 static inline void hlist_add_before(struct hlist_node *n,
    691         struct hlist_node *next) {
    692     n->pprev = next->pprev;
    693     n->next = next;
    694     next->pprev = &n->next;
    695     *(n->pprev) = n;
    696 }
    697 
    698 static inline void hlist_add_behind(struct hlist_node *n,
    699         struct hlist_node *prev) {
    700     n->next = prev->next;
    701     prev->next = n;
    702     n->pprev = &prev->next;
    703 
    704     if (n->next) {
    705         n->next->pprev = &n->next;
    706     }
    707 }
    708 
    709 /* after that we'll appear to be on some hlist and hlist_del will work */
    710 static inline void hlist_add_fake(struct hlist_node *n) {
    711     n->pprev = &n->next;
    712 }
    713 
    714 /*
    715  * Move a list from one list head to another. Fixup the pprev
    716  * reference of the first entry if it exists.
    717  */
    718 static inline void hlist_move_list(struct hlist_head *old,
    719         struct hlist_head *new) {
    720     new->first = old->first;
    721     if (new->first) {
    722         new->first->pprev = &new->first;
    723     }
    724     old->first = NULL;
    725 }
    726 
    727 #define hlist_entry(ptr, type, member) container_of(ptr,type,member)
    728 
    729 #define hlist_for_each(pos, head) 
    730     for (pos = (head)->first; pos ; pos = pos->next)
    731 
    732 #define hlist_for_each_safe(pos, n, head) 
    733     for (pos = (head)->first; pos && ({ n = pos->next; 1; }); 
    734          pos = n)
    735 
    736 #define hlist_entry_safe(ptr, type, member) 
    737     ({ typeof(ptr) ____ptr = (ptr); 
    738        ____ptr ? hlist_entry(____ptr, type, member) : NULL; 
    739     })
    740 
    741 /**
    742  * hlist_for_each_entry - iterate over list of given type
    743  * @pos:    the type * to use as a loop cursor.
    744  * @head:   the head for your list.
    745  * @member: the name of the hlist_node within the struct.
    746  */
    747 #define hlist_for_each_entry(pos, head, member)                
    748     for (pos = hlist_entry_safe((head)->first, typeof(*(pos)), member);
    749          pos;                            
    750          pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
    751 
    752 /**
    753  * hlist_for_each_entry_continue - iterate over a hlist continuing after current point
    754  * @pos:    the type * to use as a loop cursor.
    755  * @member: the name of the hlist_node within the struct.
    756  */
    757 #define hlist_for_each_entry_continue(pos, member)            
    758     for (pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member);
    759          pos;                            
    760          pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
    761 
    762 /**
    763  * hlist_for_each_entry_from - iterate over a hlist continuing from current point
    764  * @pos:    the type * to use as a loop cursor.
    765  * @member: the name of the hlist_node within the struct.
    766  */
    767 #define hlist_for_each_entry_from(pos, member)                
    768     for (; pos;                            
    769          pos = hlist_entry_safe((pos)->member.next, typeof(*(pos)), member))
    770 
    771 /**
    772  * hlist_for_each_entry_safe - iterate over list of given type safe against removal of list entry
    773  * @pos:    the type * to use as a loop cursor.
    774  * @n:      another &struct hlist_node to use as temporary storage
    775  * @head:   the head for your list.
    776  * @member: the name of the hlist_node within the struct.
    777  */
    778 #define hlist_for_each_entry_safe(pos, n, head, member)        
    779     for (pos = hlist_entry_safe((head)->first, typeof(*pos), member);
    780          pos && ({ n = pos->member.next; 1; });            
    781          pos = hlist_entry_safe(n, typeof(*pos), member))
    782 
    783 #endif // LIST_H_

    这个代码不是我写的,就是用别人现成的,具体:https://www.cnblogs.com/muahao/p/8109733.html博主的代码

    测试代码:testLi.c

     1 #include <stdio.h>                                                                                    
     2 #include <stdlib.h>
     3 #include <stdbool.h>
     4 #include "list.h"
     5 
     6 #define MaxSize 10
     7 
     8 typedef struct _stu{
     9     int id;
    10     bool sex;
    11     char name[MaxSize];
    12 
    13     struct list_head list;
    14 } Student;
    15 
    16 void creatNumStudent(Student *mylist){
    17     int num = 0;
    18     printf("please input you want create the number, not zero: ");
    19     scanf("%d", &num);
    20 
    21     for(int i=num; i!=0; --i){
    22         Student *tmp= (Student *)malloc(sizeof(Student));
    23         printf("enter id sex and name:");
    24         scanf("%d %d %s", &tmp->id, &tmp->sex, &tmp->name);
    25         list_add(&(tmp->list), &(mylist->list));
    26     }
    27     printf("
    ");
    28 
    29     return;
    30 }
    31 
    32 int main(int argc, char **argv){
    33 
    34     Student *tmp;
    35     struct list_head *pos, *q;
    36     //unsigned int i;
    37 
    38     Student mylist;
    39     INIT_LIST_HEAD(&mylist.list);
    40 
    41     creatNumStudent(&mylist);
    42 
    43     printf("traversing the list using list_for_each_entry()
    ");
    44     list_for_each_entry(tmp, &mylist.list, list)
    45         if(tmp->sex){
    46             printf("id= %d sex= %s name= %s
    ", tmp->id, "female", tmp->name);
    47         }else{
    48             printf("id= %d sex= %s name= %s
    ", tmp->id, "male", tmp->name);
    49         }
    50     printf("
    ");
    51 
    52     printf("deleting the list using list_for_each_safe()
    ");
    53     list_for_each_safe(pos, q, &mylist.list){
    54         tmp= list_entry(pos, Student, list);
    55 
    56     if(tmp->sex){
    57         printf("id= %d sex= %s name= %s
    ", tmp->id, "female", tmp->name);
    58     }else{
    59         printf("id= %d sex= %s name= %s
    ", tmp->id, "male", tmp->name);
    60     }
    61         list_del(pos);
    62         free(tmp);
    63     }
    64 
    65     return 0;
    66 }

    测试结果:

    please input you want create the number, not zero: 3   
    enter id sex and name:101 0 zhangsan
    enter id sex and name:102 1 lisi
    enter id sex and name:103 0 wangwu
    
    traversing the list using list_for_each_entry()
    id= 103 sex= male name= wangwu
    id= 102 sex= female name= lisi
    id= 101 sex= male name= zhangsan
    
    deleting the list using list_for_each_safe()
    id= 103 sex= male name= wangwu
    id= 102 sex= female name= lisi
    id= 101 sex= male name= zhangsan

    这个也是一个链表的实现,但是几乎没有实现任何的函数就实现了一个链表,主要是使用了linux的内核链表,无需自己实现,直接使用即可:由于这里的list.h文件不是自己改造的,所以目前不多说明。以下针对使用linux你和的链表使用说明如下:

    1、list.h文件中几乎实现了链表的所有操作,无论是你能想到的,或者是想不到的,安全的不安全都有了,几乎不需要添加,根据个人需求,可以把不需要的删除即可

    2、头文件中仅仅是实现了纯粹的链表,没有关联到数据,什么意思,也就是说改变数据的结构和类型,不影响链表的使用方法。

    3、内核链表打破了普通链表中的链表和数据结合很深的缺点,大大增强了链表的使用的灵活性,一般链表的实现中数据中有链表,链表中有数据,相互包含,相互引用;但是内核链表中数据和链表是经纬分明的,可以自由组合,随时能够分离的,大大提高了链表和数据使用的灵活性,增强了链表的使用的范围,缺点就是不太容易理解。

    改变数据类型:测试函数为:

     1 #include <stdio.h>
     2 #include <stdlib.h>
     3 #include <stdbool.h>
     4 #include <string.h>
     5 #include "list.h"
     6 
     7 #define MaxSize 10
     8 
     9 typedef struct _doc{
    10     int id;
    11     bool sex;
    12     char name[MaxSize];
    13     char typed[MaxSize];
    14 
    15     struct list_head list;
    16 } Doctor;
    17 
    18 void creatNumStudent(Doctor *mylist){
    19     int num = 0;
    20     printf("please input you want create the number, not zero: ");
    21     scanf("%d", &num);
    22 
    23     for(int i=num; i!=0; --i){
    24         Doctor *tmp= (Doctor *)malloc(sizeof(Doctor));
    25         printf("enter id sex and name  and typed:");
    26         scanf("%d %d %s %s", &tmp->id, &tmp->sex, &tmp->name, &tmp->typed);
    27         list_add(&(tmp->list), &(mylist->list));
    28     }
    29     printf("
    ");
    30 
    31     return;
    32 }
    33 
    34 void outputInfo(bool sex, Doctor *tmp){
    35     char str[MaxSize];
    36 
    37     if(sex){
    38         strcpy(str, "female");
    39     }else{
    40         strcpy(str, "male");
    41     }
    42 
    43     printf("id= %d sex= %s name= %s  typed= %s
    ", tmp->id, str, tmp->name, tmp->typed);
    44 
    45     return;
    46 }
    47 
    48 int main(int argc, char **argv){
    49 
    50     Doctor *tmp;
    51     struct list_head *pos, *q;
    52     //unsigned int i;
    53 
    54     Doctor mylist;
    55     INIT_LIST_HEAD(&mylist.list);
    56 
    57     creatNumStudent(&mylist);
    58 
    59     printf("traversing the list using list_for_each_entry()
    ");
    60     list_for_each_entry(tmp, &mylist.list, list){
    61         outputInfo(tmp->sex, tmp);
    62     }
    63     printf("
    ");                                                                                                
    64 
    65     printf("deleting the list using list_for_each_safe()
    ");
    66     list_for_each_safe(pos, q, &mylist.list){
    67         tmp= list_entry(pos, Doctor, list);
    68 
    69         outputInfo(tmp->sex, tmp);
    70 
    71         list_del(pos);
    72         free(tmp);
    73     }
    74 
    75     return 0;
    76 }

    测试结果为:

    please input you want create the number, not zero: 4
    enter id sex and name  and typed:101 0 zhangsan tooth
    enter id sex and name  and typed:102 1 lisi nose
    enter id sex and name  and typed:103 0 wangwu eye
    enter id sex and name  and typed:104 1 zhaoliu mouth
    
    traversing the list using list_for_each_entry()
    id= 104 sex= female name= zhaoliu  typed= mouth
    id= 103 sex= male name= wangwu  typed= eye
    id= 102 sex= female name= lisi  typed= nose
    id= 101 sex= male name= zhangsan  typed= tooth
    
    deleting the list using list_for_each_safe()
    id= 104 sex= female name= zhaoliu  typed= mouth
    id= 103 sex= male name= wangwu  typed= eye
    id= 102 sex= female name= lisi  typed= nose
    id= 101 sex= male name= zhangsan  typed= tooth

    说明:1、很明显看到,更换了数据的类型,由Student变成了Doctor,成员增加了一个,

          2、优化了性别判别的方法,代码稍微重构一下

       3、list.h中的链表的实现丝毫没有任何的改变,就让链表重新实现了新的数据的应用,是不是觉得很神奇,很不可思议,这就对了,普通人怎么能和linux的内核开发大神想的一样的呢

          4、还有一个要注意的是,这里其实也实现了数据和链表的互相隔离,从而能达到使用更加灵活的目的了。

    人就像是被蒙着眼推磨的驴子,生活就像一条鞭子;当鞭子抽到你背上时,你就只能一直往前走,虽然连你也不知道要走到什么时候为止,便一直这么坚持着。
  • 相关阅读:
    HDU 5793 A Boring Question 2016多校第六场1001
    HDU 5803 Zhu’s Math Problem 2016多校第六场1011 数位dp
    HDU 5787 K-wolf Number 2016多校第五场1007 数位dp
    HDU 5791 Two 2016多校第五场1011 LCS
    HDU 5773 The All-purpose Zero 2016多校第四场1010 LIS
    HDU 5768 Lucky7 2016多校第四场1005
    hdu 5002 Tree(LCT裸题)
    Wannafly挑战赛1 C MMSet2
    hdu 5398 GCD Tree(LCT动态维护最大生成树)
    hdu 5967 小R与手机(LCT裸题)
  • 原文地址:https://www.cnblogs.com/guochaoxxl/p/15168231.html
Copyright © 2011-2022 走看看