Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: dje@google.com
To: Yao Qi <yao@codesourcery.com>
Cc: <gdb-patches@sourceware.org>
Subject: Re: [PATCH 1/4] new gdb_queue.h in common/.
Date: Mon, 10 Sep 2012 20:47:00 -0000	[thread overview]
Message-ID: <20558.20947.170261.875294@ruffy2.mtv.corp.google.com> (raw)
In-Reply-To: <50495FFA.5080107@codesourcery.com>

Yao Qi writes:
 > On 09/05/2012 05:02 AM, dje@google.com wrote:
 > > [...]
 > > I like thinner APIs than fatter ones, but in this case I'm not sure
 > > this is better (or worth it).
 > > Thoughts?
 > > 
 > 
 > Yeah, I agree.  However, 'remove/remove_matching/find' are clear, but
 > 'iterate' with different callbacks to achieve the same task are hard to
 > read.  I post an implementation of _iterate method, and either way is OK
 > to me.

They're ok for me to read.  It might be more a matter of frequency of use.

 > 2012-09-06  Yao Qi  <yao@codesourcery.com>
 > 
 > 	* common/queue.h: New.
 > ---
 >  gdb/common/queue.h |  292 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 >  1 files changed, 292 insertions(+), 0 deletions(-)
 >  create mode 100644 gdb/common/queue.h
 > 
 > diff --git a/gdb/common/queue.h b/gdb/common/queue.h
 > new file mode 100644
 > index 0000000..fff6778
 > --- /dev/null
 > +++ b/gdb/common/queue.h
 > @@ -0,0 +1,292 @@
 > +/* General queue data structure for GDB, the GNU debugger.
 > +
 > +   Copyright (C) 2012 Free Software Foundation, Inc.
 > +
 > +   This file is part of GDB.
 > +
 > +   This program is free software; you can redistribute it and/or modify
 > +   it under the terms of the GNU General Public License as published by
 > +   the Free Software Foundation; either version 3 of the License, or
 > +   (at your option) any later version.
 > +
 > +   This program is distributed in the hope that it will be useful,
 > +   but WITHOUT ANY WARRANTY; without even the implied warranty of
 > +   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 > +   GNU General Public License for more details.
 > +
 > +   You should have received a copy of the GNU General Public License
 > +   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 > +
 > +/* These macros implement functions and structs for a general queue.  Macro
 > +   'DEFINE_QUEUE_TYPE(TYPE)' is to define the new queue type for
 > +   'TYPE', and  macro 'DECLARE_QUEUE' *is to declare these external
 > +   APIs.  */
 > +
 > +#ifndef QUEUE_H
 > +#define QUEUE_H
 > +
 > +#include <stdio.h>
 > +
 > +#include "libiberty.h" /* xmalloc */
 > +#include "gdb_assert.h"
 > +
 > +/* Define a new queue implementation.  */
 > +
 > +#define QUEUE(TYPE) struct queue_ ## TYPE
 > +#define QUEUE_ELEM(TYPE) struct queue_ele_ ## TYPE

queue_elem_ ## TYPE

 > +/* Return true if queue Q is empty.  */				\
 > +									\
 > +int									\
 > +queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q)				\
 > +{									\
 > +  gdb_assert (q != NULL);						\
 > +  return q->head == NULL;						\
 > +}									\
 > +									\
 > +void									\
 > +queue_ ## TYPE ## _remove_ele (QUEUE (TYPE) *q,			\

_remove_elem
Plus this function needs a comment.

 > +			       QUEUE_ELEM (TYPE) *p,			\
 > +			       QUEUE_ELEM (TYPE) *prev)		\
 > +{									\
 > +  if (p == q->head || p == q->tail)					\
 > +    {									\
 > +      if (p == q->head)						\
 > +	q->head = p->next;						\
 > +      if (p == q->tail)						\
 > +	q->tail = prev;						\
 > +    }									\
 > +  else									\
 > +    prev->next = p->next;						\
 > +									\
 > +  xfree (p);								\
 > +}									\
 > +									\
 > +/* Iterate over elements in the queue Q.  If function MATCH returns	\
 > +   true, call function OPERATE_ON_MATCH.   If function OPERATE_ON_MATCH \
 > +   returns true, return with true directly, otherwise, continue to	\
 > +   traverse elements in queue.  If none of elements matches, return	\
 > +   false. */								\
 > +									\
 > +int									\
 > +queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q, TYPE *v,			\
 > +			    int (*match) (TYPE, void *),		\
 > +			    int (*operate_on_match) (QUEUE (TYPE) *,	\
 > +						     QUEUE_ELEM (TYPE) *, \
 > +						     QUEUE_ELEM (TYPE) **), \
 > +			    void *data)				\

The iterator I had in mind wouldn't pass v, leaving it for the function
that is passed in to record the element found (either in *data directly,
or as part of the struct that data points to).
Also, I had envisioned just passing in one function, say "operate".

Thus:

int
queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q,
			    int (*operate) (QUEUE (TYPE) *,
					    QUEUE_ITER (TYPE) *,
					    QUEUE_ELEM (TYPE) *,
					    void *),
			    void *data)

operate would return 0 to terminate the iteration
and 1 to continue the iteration
(akin to hashtab.h:htab_trav - Consistency Is Good!).

QUEUE_ITER abstracts away the implementation details,
and is passed to _remove_elem.

I wasn't thinking of including _find, _remove, _remove_matching
in the API if we have an iterator - let the user write one if
desired for his/her particular type.
I was expecting users to write "operate" and then just call the
_iterate.

If you want _find,_remove,_remove_matching in the API,
it's not that big a deal.  You *could* leave _iterate for later then.
I just want to make sure you've thought about it.

 > +{									\
 > +  int matches = 0;							\
 > +									\
 > +  QUEUE_ELEM (TYPE) *p;						\
 > +  QUEUE_ELEM (TYPE) *prev = NULL, *next = NULL;			\
 > +									\
 > +  gdb_assert (q != NULL);						\
 > +									\
 > +  for (p = q->head; p != NULL; p = next)				\
 > +    {									\
 > +      next = p->next;							\
 > +      if (match (p->data, data))					\
 > +	{								\
 > +	  matches = 1;							\
 > +	  if (v != NULL)						\
 > +	    *v = p->data;						\
 > +									\
 > +	  if (operate_on_match (q, p, &prev))				\
 > +	    return 1;							\
 > +	}								\
 > +      else								\
 > +	prev = p;							\
 > +    }									\
 > +  return matches;							\
 > +}									\
 > +									\
 > +static int								\
 > +queue_ ## TYPE ##_on_match_once (QUEUE (TYPE) *q, QUEUE_ELEM (TYPE) *p, \
 > +				 QUEUE_ELEM (TYPE) **prev)		\
 > +{									\
 > +  return 1;								\
 > +}									\
 > +									\
 > +/* Find the first element in queue Q for which function MATCH returns	\
 > +   true.  Return true if found, and store the found element in V.	\
 > +   Otherwise return false..  */					\
 > +									\
 > +int									\
 > +queue_ ## TYPE ## _find (QUEUE (TYPE) *q, TYPE *v,			\
 > +			 int (*match) (TYPE, void *),			\
 > +			 void *data)					\
 > +{									\
 > +  return queue_ ## TYPE ## _iterate (q, v, match,			\
 > +				     queue_ ## TYPE ##_on_match_once, data); \
 > +}									\
 > +									\
 > +/* Allocate memory for queue.  */					\
 > +									\
 > +QUEUE (TYPE) *								\
 > +queue_ ## TYPE ## _alloc (void (*free_func) (TYPE))			\
 > +{									\
 > +  QUEUE (TYPE) *q;							\
 > +									\
 > +  q = (QUEUE (TYPE) *) xmalloc (sizeof (QUEUE (TYPE)));\
 > +  q->head = NULL;							\
 > +  q->tail = NULL;							\
 > +  q->free_func = free_func;						\
 > +  return q;								\
 > +}									\
 > +									\
 > +/* Length of queue Q.  */						\
 > +									\
 > +int									\
 > +queue_ ## TYPE ## _length (QUEUE (TYPE) *q)				\
 > +{									\
 > +  QUEUE_ELEM (TYPE) *p;						\
 > +  int len = 0;								\
 > +									\
 > +  gdb_assert (q != NULL);						\
 > +									\
 > +  for (p = q->head; p != NULL; p = p->next)				\
 > +    len++;								\
 > +									\
 > +  return len;								\
 > +}									\

blank line here

 > +/* Free memory for queue Q.  */					\
 > +									\
 > +void									\
 > +queue_ ## TYPE ## _free (QUEUE (TYPE) *q)				\
 > +{									\
 > +  QUEUE_ELEM (TYPE) *p, *next;						\
 > +									\
 > +  gdb_assert (q != NULL);						\
 > +									\
 > +  for (p = q->head; p != NULL; p = next)				\
 > +    {									\
 > +      next = p->next;							\
 > +      if (q->free_func)						\
 > +	q->free_func (p->data);					\
 > +      xfree (p);							\
 > +    }									\
 > +  xfree (q);								\
 > +}									\
 > +
 > +/* External declarations for these functions.  */
 > +#define DECLARE_QUEUE_P(TYPE)					\
 > +QUEUE (TYPE);							\
 > +QUEUE_ELEM (TYPE);						\
 > +extern void							\
 > +  queue_ ## TYPE ## _enque (QUEUE (TYPE) *q, TYPE v);		\
 > +extern TYPE							\
 > +  queue_ ## TYPE ## _deque (QUEUE (TYPE) *q);			\
 > +extern int queue_ ## TYPE ## _is_empty (QUEUE (TYPE) *q);	\
 > +extern int							\
 > +  queue_ ## TYPE ## _find (QUEUE (TYPE) *, TYPE *v,		\
 > +			   int (*match) (TYPE, void *),	\
 > +			   void *data);			\
 > +extern QUEUE (TYPE) *						\
 > +  queue_ ## TYPE ## _alloc (void (*free_func) (TYPE));		\
 > +extern int queue_ ## TYPE ## _length (QUEUE (TYPE) *q);	\
 > +extern TYPE							\
 > +  queue_ ## TYPE ## _peek (QUEUE (TYPE) *q);			\
 > +extern void queue_ ## TYPE ## _free (QUEUE (TYPE) *q);		\
 > +extern int							\
 > +  queue_ ## TYPE ## _iterate (QUEUE (TYPE) *q, TYPE *v,	\
 > +			      int (*match) (TYPE, void *),		\
 > +			      int (*operate_on_match) (QUEUE (TYPE) *,	\
 > +						       QUEUE_ELEM (TYPE) *, \
 > +						       QUEUE_ELEM (TYPE) **), \
 > +			      void *data);				\
 > +extern void queue_ ## TYPE ## _remove_ele (QUEUE (TYPE) *q,		\
 > +					   QUEUE_ELEM (TYPE) *p,	\
 > +					   QUEUE_ELEM (TYPE) *prev);	\
 > +
 > +#define QUEUE_enque(TYPE, QUEUE, V) queue_ ## TYPE ## _enque ((QUEUE), (V))
 > +#define QUEUE_deque(TYPE, QUEUE) queue_ ## TYPE ## _deque (QUEUE)
 > +#define QUEUE_peek(TYPE, QUEUE) queue_ ## TYPE ## _peek (QUEUE)
 > +#define QUEUE_is_empty(TYPE, QUEUE) queue_ ## TYPE ## _is_empty (QUEUE)
 > +#define QUEUE_find(TYPE, QUEUE, V, MATCH, DATA)	\
 > +  queue_ ## TYPE ## _find ((QUEUE), (V), (MATCH), (DATA))
 > +#define QUEUE_alloc(TYPE, FREE_FUNC) queue_ ## TYPE ## _alloc (FREE_FUNC)
 > +#define QUEUE_length(TYPE, QUEUE) queue_ ## TYPE ## _length (QUEUE)
 > +#define QUEUE_free(TYPE, QUEUE) queue_ ## TYPE ## _free (QUEUE)
 > +#define QUEUE_iterate(TYPE, QUEUE, V, MATCH, OP_ON_MATCH, DATA)	\
 > +  queue_ ## TYPE ## _iterate ((QUEUE), (V), (MATCH), (OP_ON_MATCH), (DATA))
 > +#define QUEUE_remove_ele(TYPE, QUEUE, P, PREV) \
 > +  queue_ ## TYPE ## _remove_ele ((QUEUE), (P), (PREV))
 > +
 > +#endif /* QUEUE_H */
 > -- 


  reply	other threads:[~2012-09-10 20:47 UTC|newest]

Thread overview: 19+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-24  2:26 [RCF 0/4] A general notification in GDB RSP Yao Qi
2012-08-24  2:26 ` [PATCH 2/4] de-couple %Stop from notification: gdb Yao Qi
2012-08-24 16:52   ` Yao Qi
2012-08-24 19:00   ` dje
2012-08-30  6:40     ` Yao Qi
2012-08-24  2:26 ` [PATCH 3/4] de-couple %Stop from notification: gdbserver Yao Qi
2012-08-24  2:26 ` [PATCH 1/4] new gdb_queue.h in common/ Yao Qi
2012-08-24 18:44   ` dje
2012-08-24 18:49     ` Doug Evans
2012-08-29  9:42     ` Yao Qi
2012-09-04 21:03       ` dje
2012-09-07  2:47         ` Yao Qi
2012-09-10 20:47           ` dje [this message]
2012-09-12 14:24             ` Yao Qi
2012-09-13 15:55               ` dje
2012-09-14  2:38                 ` Yao Qi
2012-09-11 16:50         ` Tom Tromey
2012-08-24  2:26 ` [PATCH 4/4] new notification "TEST" Yao Qi
2012-08-24 17:53 ` [RCF 0/4] A general notification in GDB RSP Pedro Alves

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20558.20947.170261.875294@ruffy2.mtv.corp.google.com \
    --to=dje@google.com \
    --cc=gdb-patches@sourceware.org \
    --cc=yao@codesourcery.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox