On Tue, May 04, 2010 at 09:25:29PM +0200, Tim van der Molen wrote:
> On Tue, 04 May 2010 00:20:47 +0200, Nicholas Marriott wrote:
> > SPLAY_REMOVE appears to returns the pointer it is given or NULL if the
> > item isn't found. I don't see what errors it could return NULL for, so I
> > think it would be better to say "NULL is returned if no item with that
> > key is found". Or at least if you can spot any errors I can't, "to
> > indicate an error or that the key is not found".
> 
> How about "If the element does not exist in the tree, NULL is returned"?
> Below is an updated version of the original diff.
> 
> > RB_REMOVE returns the pointer it is given whether or not the item is in
> > the tree (even for an empty tree). This seems unexpected, so it might be
> > a bug...
> 
> I think you're right. If I'm not mistaken, RB_REMOVE will have to
> explicitly check whether the element exists in the tree. The second diff
> below uses RB_FIND to do that. I'm not sure what consequences this has

I don't think we should do this, at least not without knowing the
performance change. The return value of *_REMOVE is very rarely used, I
think just documenting it is fine.

I'm going to put in a tweaked version of your original diff soon.

> for performance. Actually, I'm not sure it's an elegant fix in the first
> place.
> 
> The second diff also removes an unnecessary variable.

I'll look at this as well.

Thanks!

> 
> Index: tree.3
> ===================================================================
> RCS file: /cvs/src/share/man/man3/tree.3,v
> retrieving revision 1.20
> diff -u tree.3
> --- tree.3    28 Jan 2009 12:22:48 -0000      1.20
> +++ tree.3    4 May 2010 19:10:37 -0000
> @@ -257,14 +257,24 @@
>  .Fn SPLAY_INSERT
>  macro inserts the new element
>  .Fa elm
> -into the tree.
> +into the tree pointed to by
> +.Fa head .
> +Upon success,
> +.Va NULL
> +is returned.
> +If a matching element already exists in the tree, the insertion is
> +aborted, and a pointer to the existing element is returned.
>  .Pp
>  The
>  .Fn SPLAY_REMOVE
>  macro removes the element
>  .Fa elm
> -from the tree pointed by
> +from the tree pointed to by
>  .Fa head .
> +Upon success, a pointer to the removed element is returned.
> +If the element does not exist in the tree,
> +.Va NULL
> +is returned.
>  .Pp
>  The
>  .Fn SPLAY_FIND
> @@ -392,7 +402,8 @@
>  .Fn RB_INSERT
>  macro inserts the new element
>  .Fa elm
> -into the tree.
> +into the tree pointed to by
> +.Fa head .
>  Upon success,
>  .Va NULL
>  is returned.
> @@ -403,8 +414,12 @@
>  .Fn RB_REMOVE
>  macro removes the element
>  .Fa elm
> -from the tree pointed by
> +from the tree pointed to by
>  .Fa head .
> +Upon success, a pointer to the removed element is returned.
> +If the element does not exist in the tree,
> +.Va NULL
> +is returned.
>  .Pp
>  The
>  .Fn RB_FIND
> @@ -543,22 +558,5 @@
>       free(var);
>  }
>  .Ed
> -.Pp
> -Both
> -.Fn RB_INSERT
> -and
> -.Fn SPLAY_INSERT
> -return
> -.Va NULL
> -if the element was inserted in the tree successfully, otherwise they
> -return a pointer to the element with the colliding key.
> -.Pp
> -Accordingly,
> -.Fn RB_REMOVE
> -and
> -.Fn SPLAY_REMOVE
> -return the pointer to the removed element, otherwise they return
> -.Va NULL
> -to indicate an error.
>  .Sh AUTHORS
>  The author of the tree macros is Niels Provos.
> 
> Index: tree.h
> ===================================================================
> RCS file: /cvs/src/sys/sys/tree.h,v
> retrieving revision 1.12
> diff -p -u tree.h
> --- tree.h    2 Mar 2009 09:42:55 -0000       1.12
> +++ tree.h    4 May 2010 19:20:30 -0000
> @@ -521,7 +521,8 @@ attr struct type *                                        
>                 \
>  name##_RB_REMOVE(struct name *head, struct type *elm)                        
> \
>  {                                                                    \
>       struct type *child, *parent, *old = elm;                        \
> -     int color;                                                      \
> +     if (name##_RB_FIND(head, elm) == NULL)                          \
> +             return (NULL);                                          \
>       if (RB_LEFT(elm, field) == NULL)                                \
>               child = RB_RIGHT(elm, field);                           \
>       else if (RB_RIGHT(elm, field) == NULL)                          \
> @@ -533,7 +534,6 @@ name##_RB_REMOVE(struct name *head, struct type *elm)     
>                       elm = left;                                     \
>               child = RB_RIGHT(elm, field);                           \
>               parent = RB_PARENT(elm, field);                         \
> -             color = RB_COLOR(elm, field);                           \
>               if (child)                                              \
>                       RB_PARENT(child, field) = parent;               \
>               if (parent) {                                           \
> @@ -567,7 +567,6 @@ name##_RB_REMOVE(struct name *head, struct type *elm)     
>               goto color;                                             \
>       }                                                               \
>       parent = RB_PARENT(elm, field);                                 \
> -     color = RB_COLOR(elm, field);                                   \
>       if (child)                                                      \
>               RB_PARENT(child, field) = parent;                       \
>       if (parent) {                                                   \
> @@ -579,7 +578,7 @@ name##_RB_REMOVE(struct name *head, struct type *elm)     
>       } else                                                          \
>               RB_ROOT(head) = child;                                  \
>  color:                                                                       
> \
> -     if (color == RB_BLACK)                                          \
> +     if (RB_COLOR(elm, field) == RB_BLACK)                           \
>               name##_RB_REMOVE_COLOR(head, parent, child);            \
>       return (old);                                                   \
>  }                                                                    \

Reply via email to