Hello

This is implementaion of circular doubly linked parametrized list.
It is similar to the list implementation in include/linux/list.h
but it also provides type safety which allows to detect some of list 
manipulating
mistakes as soon as they happen.

Please consider how feasible is a chance to have this patch accepted.
These lists are widely used by reiser4. I believe others may find it useful.

Thanks
This is implementaion of circular doubly linked parametrized list.
It is similar to the list implementation in include/linux/list.h
but it also provides type safety which allows to detect some of list 
manipulating
mistakes as soon as they happen.


 include/linux/type_safe_list.h |  433 +++++++++++++++++++++++++++++++++++++++++
 1 files changed, 433 insertions(+)

diff -puN /dev/null include/linux/type_safe_list.h
--- /dev/null   2003-09-23 21:59:22.000000000 +0400
+++ linux-2.6.12-vs/include/linux/type_safe_list.h      2005-07-14 
19:28:46.839464437 +0400
@@ -0,0 +1,433 @@
+#ifndef _LINUX_TYPE_SAFE_LIST_H
+#define _LINUX_TYPE_SAFE_LIST_H
+
+/* A circular doubly linked list that differs from the previous
+   <linux/list.h> implementation because it is parametrized to provide
+   type safety.  This data structure is also useful as a queue or stack.
+
+   The "list template" consists of a set of types and methods for
+   implementing list operations.  All of the types and methods
+   associated with a single list class are assigned unique names and
+   type signatures, thus allowing the compiler to verify correct
+   usage.
+
+   The first parameter of a list class is the item type being stored
+   in the list.  The list class maintains two pointers within each
+   item structure for its "next" and "prev" pointers.
+
+   There are two structures associated with the list, in addition to
+   the item type itself.  The "list link" contains the two pointers
+   that are embedded within the item itself.  The "list head" also
+   contains two pointers which refer to the first item ("front") and
+   last item ("back") of the list.
+
+   The list maintains a "circular" invariant, in that you can always
+   begin at the front and follow "next" pointers until eventually you
+   reach the same point.  The "list head" is included within the
+   cycle, even though it does not have the correct item type.  The
+   "list head" and "list link" types are different objects from the
+   user's perspective, but the core algorithms that operate on this
+   style of list treat the "list head" and "list link" as identical
+   types.  That is why these algorithms are so simple.
+
+   The <linux/list.h> implementation uses the same algorithms as those
+   in this file but uses only a single type "struct list_head".  There
+   are two problems with this approach.  First, there are no type
+   distinctions made between the two objects despite their distinct
+   types, which greatly increases the possibility for mistakes.  For
+   example, the <linux/list.h> list_add function takes two "struct
+   list_head" arguments: the first is the item being inserted and the
+   second is the "struct list_head" which should precede the new
+   insertion to the list.  You can use this function to insert at any
+   point in the list, but by far the most common list operations are
+   to insert at the front or back of the list.  This common case
+   should accept two different argument types: a "list head" and an
+   "item", this allows for no confusion.
+
+   The second problem with using a single "struct list_head" is that
+   it does not distinguish between list objects of distinct list
+   classes.  If a single item can belong to two separate lists, there
+   is easily the possibility of a mistake being made that causes the
+   item to be added to a "list head" using the wrong "list link".  By
+   using a parametrized list class we can statically detect such
+   mistakes, detecting mistakes as soon as they happen.
+
+   To create a new list class takes several steps which are described
+   below.  Suppose for this example that you would like to link
+   together items of type "rx_event".  You should decide on
+   prefix-name to be used on all list functions and structures.  For
+   example, the string "rx_event" can be as a prefix for all the list
+   operations, resulting in a "list head" named rx_event_list_head and
+   a "list link" named rx_event_list_link.  The list operations on
+   this list class would be named "rx_event_list_empty",
+   "rx_event_list_init", "rx_event_list_push_front",
+   "rx_event_list_push_back", and so on.
+*/
+
+#define TYPE_SAFE_LIST_LINK_INIT(name) { &(name), &(name) }
+#define TYPE_SAFE_LIST_HEAD_INIT(name) { (void *)&(name), (void *)&(name) }
+#define TYPE_SAFE_LIST_LINK_ZERO { NULL, NULL }
+#define TYPE_SAFE_LIST_HEAD_ZERO { NULL, NULL }
+
+#define TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,LINK) \
+       ((ITEM_TYPE *)((char *)(LINK)-(unsigned long)(&((ITEM_TYPE 
*)0)->LINK_NAME)))
+
+/* Step 1: Use the TYPE_SAFE_LIST_DECLARE() macro to define the "list head"
+   and "list link" objects.  This macro takes one arguments, the
+   prefix-name, which is prepended to every structure and function
+   name of the list class.  Following the example, this will create
+   types named rx_event_list_head and rx_event_list_link.  In the
+   example you would write:
+
+   TYPE_SAFE_LIST_DECLARE(rx_event);
+
+*/
+#define TYPE_SAFE_LIST_DECLARE(PREFIX)                         \
+                                                               \
+typedef struct _##PREFIX##_list_head        PREFIX##_list_head;        \
+typedef struct _##PREFIX##_list_link        PREFIX##_list_link;        \
+                                                               \
+struct _##PREFIX##_list_link                                   \
+{                                                              \
+       PREFIX##_list_link *_next;                              \
+       PREFIX##_list_link *_prev;                              \
+};                                                             \
+                                                               \
+struct _##PREFIX##_list_head                                   \
+{                                                              \
+       PREFIX##_list_link *_next;                              \
+       PREFIX##_list_link *_prev;                              \
+}
+
+/* Step 2: Once you have defined the two list classes, you should
+   define the item type you intend to use.  The list classes must be
+   declared before the item type because the item type must contain an
+   embedded "list link" object.  Following the example, you might define
+   rx_event as follows:
+
+   typedef struct _rx_event  rx_event;
+
+   struct _rx_event
+   {
+     ... other members ...
+
+     rx_event_list_link  _link;
+   };
+
+   In this case we have given the rx_event a field named "_link" of
+   the appropriate type.
+*/
+
+/* Step 3: The final step will define the list-functions for a
+   specific list class using the macro TYPE_SAFE_LIST_DEFINE.  There are
+   three arguments to the TYPE_SAFE_LIST_DEFINE macro: the prefix-name, the
+   item type name, and field name of the "list link" element within
+   the item type.  In the above example you would supply "rx_event" as
+   the type name and "_link" as the field name (without quotes).
+   E.g.,
+
+   TYPE_SAFE_LIST_DEFINE(rx_event,rx_event,_link)
+
+   The list class you define is now complete with the functions:
+
+   rx_event_list_init             Initialize a list_head
+   rx_event_list_clean            Initialize a list_link
+   rx_event_list_is_clean         True if list_link is not in a list
+   rx_event_list_push_front       Insert to the front of the list
+   rx_event_list_push_back        Insert to the back of the list
+   rx_event_list_insert_before    Insert just before given item in the list
+   rx_event_list_insert_after     Insert just after given item in the list
+   rx_event_list_remove           Remove an item from anywhere in the list
+   rx_event_list_remove_clean     Remove an item from anywhere in the list and 
clean link_item
+   rx_event_list_remove_get_next  Remove an item from anywhere in the list and 
return the next element
+   rx_event_list_remove_get_prev  Remove an item from anywhere in the list and 
return the prev element
+   rx_event_list_pop_front        Remove and return the front of the list, 
cannot be empty
+   rx_event_list_pop_back         Remove and return the back of the list, 
cannot be empty
+   rx_event_list_front            Get the front of the list
+   rx_event_list_back             Get the back of the list
+   rx_event_list_next             Iterate front-to-back through the list
+   rx_event_list_prev             Iterate back-to-front through the list
+   rx_event_list_end              Test to end an iteration, either direction
+   rx_event_list_splice           Join two lists at the head
+   rx_event_list_empty            True if the list is empty
+   rx_event_list_object_ok        Check that list element satisfies double
+                                  list invariants. For debugging.
+
+   To iterate over such a list use a for-loop such as:
+
+     rx_event_list_head *head = ...;
+     rx_event *item;
+
+     for (item = rx_event_list_front (head);
+               ! rx_event_list_end   (head, item);
+          item = rx_event_list_next  (item))
+       {...}
+*/
+#define TYPE_SAFE_LIST_DEFINE(PREFIX,ITEM_TYPE,LINK_NAME)                      
                \
+                                                                               
                \
+static __inline__ int                                                          
                \
+PREFIX##_list_link_invariant (const PREFIX##_list_link  *_link)                
                        \
+{                                                                              
                \
+       return (_link != NULL) &&                                               
                \
+               (_link->_prev != NULL) && (_link->_next != NULL ) &&            
                \
+               (_link->_prev->_next == _link) &&                               
                \
+               (_link->_next->_prev == _link);                                 
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_link_ok (const PREFIX##_list_link  *_link UNUSED_ARG)            
                \
+{                                                                              
                \
+       BUG_ON(!PREFIX##_list_link_invariant (_link));                          
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_object_ok (const ITEM_TYPE           *item)                      
                \
+{                                                                              
                \
+       PREFIX##_list_link_ok (&item->LINK_NAME);                               
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_init (PREFIX##_list_head  *head)                                 
                \
+{                                                                              
                \
+       head->_next = (PREFIX##_list_link*) head;                               
                \
+       head->_prev = (PREFIX##_list_link*) head;                               
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_clean (ITEM_TYPE           *item)                                
                        \
+{                                                                              
                \
+       PREFIX##_list_link *_link = &item->LINK_NAME;                           
                \
+                                                                               
                \
+       _link->_next = _link;                                                   
                \
+       _link->_prev = _link;                                                   
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ int                                                          
                \
+PREFIX##_list_is_clean (const ITEM_TYPE           *item)                       
                \
+{                                                                              
                \
+       const PREFIX##_list_link *_link = &item->LINK_NAME;                     
                \
+                                                                               
                \
+       PREFIX##_list_link_ok (_link);                                          
                \
+       return (_link == _link->_next) && (_link == _link->_prev);              
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_insert_int (PREFIX##_list_link  *next,                           
                \
+                         PREFIX##_list_link  *item)                            
                \
+{                                                                              
                \
+       PREFIX##_list_link *prev = next->_prev;                                 
                \
+       PREFIX##_list_link_ok (next);                                           
                \
+       PREFIX##_list_link_ok (prev);                                           
                \
+       next->_prev = item;                                                     
                \
+       item->_next = next;                                                     
                \
+       item->_prev = prev;                                                     
                \
+       prev->_next = item;                                                     
                \
+       PREFIX##_list_link_ok (next);                                           
                \
+       PREFIX##_list_link_ok (prev);                                           
                \
+       PREFIX##_list_link_ok (item);                                           
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_push_front (PREFIX##_list_head  *head,                           
                \
+                         ITEM_TYPE           *item)                            
                \
+{                                                                              
                \
+       PREFIX##_list_insert_int (head->_next, & item->LINK_NAME);              
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_push_back (PREFIX##_list_head  *head,                            
                \
+                        ITEM_TYPE           *item)                             
                \
+{                                                                              
                \
+       PREFIX##_list_insert_int ((PREFIX##_list_link *) head, & 
item->LINK_NAME);              \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_insert_before (ITEM_TYPE         *reference,                     
                \
+                            ITEM_TYPE           *item)                         
                \
+{                                                                              
                \
+       PREFIX##_list_insert_int (& reference->LINK_NAME, & item->LINK_NAME);   
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_insert_after (ITEM_TYPE         *reference,                      
                \
+                           ITEM_TYPE           *item)                          
                \
+{                                                                              
                \
+       PREFIX##_list_insert_int (reference->LINK_NAME._next, & 
item->LINK_NAME);               \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ PREFIX##_list_link*                                          
                \
+PREFIX##_list_remove_int (PREFIX##_list_link *list_link)                       
                \
+{                                                                              
                \
+       PREFIX##_list_link *next = list_link->_next;                            
                \
+       PREFIX##_list_link *prev = list_link->_prev;                            
                \
+       PREFIX##_list_link_ok (list_link);                                      
                \
+       PREFIX##_list_link_ok (next);                                           
                \
+       PREFIX##_list_link_ok (prev);                                           
                \
+       next->_prev = prev;                                                     
                \
+       prev->_next = next;                                                     
                \
+       PREFIX##_list_link_ok (next);                                           
                \
+       PREFIX##_list_link_ok (prev);                                           
                \
+       return list_link;                                                       
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_remove (ITEM_TYPE  *item)                                        
                        \
+{                                                                              
                \
+       PREFIX##_list_remove_int (& item->LINK_NAME);                           
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_remove_clean (ITEM_TYPE  *item)                                  
                \
+{                                                                              
                \
+       PREFIX##_list_remove_int (& item->LINK_NAME);                           
                \
+       PREFIX##_list_clean (item);                                             
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_remove_get_next (ITEM_TYPE  *item)                               
                \
+{                                                                              
                \
+       PREFIX##_list_link *next = item->LINK_NAME._next;                       
                \
+       PREFIX##_list_remove_int (& item->LINK_NAME);                           
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,next);                       
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_remove_get_prev (ITEM_TYPE  *item)                               
                \
+{                                                                              
                \
+       PREFIX##_list_link *prev = item->LINK_NAME._prev;                       
                \
+       PREFIX##_list_remove_int (& item->LINK_NAME);                           
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,prev);                       
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ int                                                          
                \
+PREFIX##_list_empty (const PREFIX##_list_head  *head)                          
                \
+{                                                                              
                \
+       return head == (PREFIX##_list_head*) head->_next;                       
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_pop_front (PREFIX##_list_head  *head)                            
                \
+{                                                                              
                \
+       BUG_ON(PREFIX##_list_empty (head));                                     
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,PREFIX##_list_remove_int 
(head->_next));     \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_pop_back (PREFIX##_list_head  *head)                             
                \
+{                                                                              
                \
+       BUG_ON(PREFIX##_list_empty (head)); /* WWI started */                   
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,PREFIX##_list_remove_int 
(head->_prev));     \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_front (const PREFIX##_list_head  *head)                          
                \
+{                                                                              
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,head->_next);                
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_back (const PREFIX##_list_head  *head)                           
                \
+{                                                                              
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,head->_prev);                
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_next (const ITEM_TYPE *item)                                     
                \
+{                                                                              
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,item->LINK_NAME._next);      
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ ITEM_TYPE*                                                   
                \
+PREFIX##_list_prev (const ITEM_TYPE *item)                                     
                \
+{                                                                              
                \
+       return TS_LINK_TO_ITEM(ITEM_TYPE,LINK_NAME,item->LINK_NAME._prev);      
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ int                                                          
                \
+PREFIX##_list_end (const PREFIX##_list_head  *head,                            
                \
+                  const ITEM_TYPE           *item)                             
                \
+{                                                                              
                \
+       return ((PREFIX##_list_link *) head) == (& item->LINK_NAME);            
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_splice (PREFIX##_list_head  *head_join,                          
                \
+                     PREFIX##_list_head  *head_empty)                          
                \
+{                                                                              
                \
+       if (PREFIX##_list_empty (head_empty)) {                                 
                \
+               return;                                                         
                \
+       }                                                                       
                \
+                                                                               
                \
+       head_empty->_prev->_next = (PREFIX##_list_link*) head_join;             
                \
+       head_empty->_next->_prev = head_join->_prev;                            
                \
+                                                                               
                \
+       head_join->_prev->_next  = head_empty->_next;                           
                \
+       head_join->_prev         = head_empty->_prev;                           
                \
+                                                                               
                \
+       PREFIX##_list_link_ok ((PREFIX##_list_link*) head_join);                
                \
+       PREFIX##_list_link_ok (head_join->_prev);                               
                \
+       PREFIX##_list_link_ok (head_join->_next);                               
                \
+                                                                               
                \
+       PREFIX##_list_init (head_empty);                                        
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_split(PREFIX##_list_head  *head_split,                           
                \
+                   PREFIX##_list_head  *head_new,                              
                \
+                   ITEM_TYPE  *item)                                           
                \
+{                                                                              
                \
+       BUG_ON(!PREFIX##_list_empty(head_new));                                 
                \
+                                                                               
                \
+       /* attach to new list */                                                
                \
+       head_new->_next = (& item->LINK_NAME);                                  
                \
+       head_new->_prev = head_split->_prev;                                    
                \
+                                                                               
                \
+       /* cut from old list */                                                 
                \
+       item->LINK_NAME._prev->_next = (PREFIX##_list_link*)head_split;         
                \
+       head_split->_prev = item->LINK_NAME._prev;                              
                \
+                                                                               
                \
+       /* link new list */                                                     
                \
+       head_new->_next->_prev = (PREFIX##_list_link*)head_new;                 
                \
+       head_new->_prev->_next = (PREFIX##_list_link*)head_new;                 
                \
+}                                                                              
                \
+                                                                               
                \
+static __inline__ void                                                         
                \
+PREFIX##_list_check (const PREFIX##_list_head  *head)                          
                \
+{                                                                              
                \
+       const PREFIX##_list_link *link;                                         
                \
+                                                                               
                \
+       for (link = head->_next ; link != ((PREFIX##_list_link *) head) ; link 
= link->_next)   \
+               PREFIX##_list_link_ok (link);                                   
                \
+}                                                                              
                \
+                                                                               
                \
+typedef struct { int foo; } PREFIX##_list_dummy_decl
+
+/* The final typedef is to allow a semicolon at the end of
+ * TYPE_SAFE_LIST_DEFINE(); */
+
+#define for_all_type_safe_list(prefix, head, item)             \
+       for(item = prefix ## _list_front(head),                 \
+                   prefetch(prefix ## _list_next(item));       \
+           !prefix ## _list_end(head, item) ;                  \
+           item = prefix ## _list_next(item),                  \
+                   prefetch(prefix ## _list_next(item)))
+
+#define for_all_type_safe_list_safe(prefix, head, item, next)  \
+       for(item = prefix ## _list_front(head),                 \
+            next = prefix ## _list_next(item);                 \
+           !prefix ## _list_end(head, item) ;                  \
+           item = next,                                        \
+           next = prefix ## _list_next(item))
+
+/* _LINUX_TYPE_SAFE_LIST_H */
+#endif
+
+/*
+   Local variables:
+   c-indentation-style: "K&R"
+   mode-name: "LC"
+   c-basic-offset: 8
+   tab-width: 8
+   fill-column: 120
+   End:
+*/

_

Reply via email to