[Freeciv-Dev] (PR#40596) [Patch] Generic iterator interface

2008-12-11 Thread Madeline Book

URL: http://bugs.freeciv.org/Ticket/Display.html?id=40596 

 [book - Thu Dec 11 06:36:54 2008]:
 
 Attached patch adds a generic iterator interface for
 implementing iteration macros.
 
 [...]

 Now while the 4 goals listed above should be satisfied by
 this framework, there are some disadvantages to this
 particular implementation of the system:
 
 [...]

I would add to the list of disadvantages that using the
'return' statment in a generic_iterate macro prevents the
iterator from being freed. This is a pretty big deal-
breaker in my opinion. :(

I do have an idea on how to fix 3 of the 4 disadvantages
though, so I will try a second version soon. :)


---
ああそう。興奮してる。

___
Freeciv-dev mailing list
Freeciv-dev@gna.org
https://mail.gna.org/listinfo/freeciv-dev


[Freeciv-Dev] (PR#40596) [Patch] Generic iterator interface

2008-12-10 Thread Madeline Book

URL: http://bugs.freeciv.org/Ticket/Display.html?id=40596 

Attached patch adds a generic iterator interface for
implementing iteration macros. This framework serves
the following purposes:

1. Hide specific container and iterator implementation
   details from other code modules, in particular
   remove the need for the iteration macros defined in
   header files to have access to container internals.
2. Preserve constness of containers when iterating over
   them, i.e. the container is not modified when using
   an iteration macro.
3. Reduce code duplication in iteration macros, i.e.
   have specific iteration macros only change what needs
   to be changed rather than rewriting the whole loop
   structure each time.
4. Ensure that iteration over a sequence of N values
   has O(N) time complexity.


The interface is used as follows. Suppose we wish to add
iteration macros for the opaque type 'foo'. In foo's
header file we add:

#include iterator.h
struct iterator *foo_get_iter(const struct foo *pfoo);
#define foo_thing_iterate(pfoo, pthing)\
  generic_iterate(foo_get_iter(pfoo), struct thing *, pthing)
#define foo_thing_iterate_end generic_iterate_end

Then in foo's code module we define a derived iterator
type, say 'foo_thing_iterator', which provides implementations
for the 4 iterator interface functions next, free, get and
valid. The body of foo_get_iter() creates the derived
iterator (setting up its vtable, i.e. function pointers)
and returns it as a base class iterator pointer.

Now we can iterate over foo's things like:

#include foo.h
... /* Make a foo, add some things. */
foo_thing_iterate(pfoo, pthing) {
  ... /* Use pthing */
} foo_thing_iterate_end;


Now while the 4 goals listed above should be satisfied by
this framework, there are some disadvantages to this
particular implementation of the system:
1. Iterators are allocated on the heap and free'd after the
   iteration loop, which is possibly slower than if they
   were just variables allocated on the stack.
2. The virtual functions incur at least an extra pointer
   dereference when ever they are used. Since there are
   usually 3 virtual calls per loop iteration, this could
   be a significant running time overhead.
3. The actual generic_iterate macro body is pretty hairy,
   using token concatenation and a for-loop syntax hack
   to allow nesting of itself and to ensure iterators are
   always free'd.


So I'm not sure whether this is really necessary, or whether
it is overkill for the purposes of the code base. Anyway I
will let it sit a bit for your examination and try out some
uses of it in subsequent patches.


---
忘れずに空腹衝動を戻しなさい。
 utility/Makefile.am |1 +
 utility/iterator.h  |   92 +++
 2 files changed, 93 insertions(+), 0 deletions(-)

diff --git a/utility/Makefile.am b/utility/Makefile.am
index 106d87f..5dbbe12 100644
--- a/utility/Makefile.am
+++ b/utility/Makefile.am
@@ -23,6 +23,7 @@ libcivutility_a_SOURCES = \
 		inputfile.h	\
 		ioz.c		\
 		ioz.h		\
+		iterator.h	\
 		log.c		\
 		log.h		\
 		netintf.c	\
diff --git a/utility/iterator.h b/utility/iterator.h
new file mode 100644
index 000..c701f4e
--- /dev/null
+++ b/utility/iterator.h
@@ -0,0 +1,92 @@
+/***
+ Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
+   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 2, 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.
+***/
+#ifndef FC__ITERATOR_H
+#define FC__ITERATOR_H
+
+/***
+  Iterator base class. Derived iterators must have this struct as
+  their first member (as a vtable) and provide implementations of
+  the pure virtual member functions. See the function comment headers
+  below for the expected behaviour of these functions.
+***/
+struct iterator {
+  void (*next)(struct iterator *it);
+  void (*free)(struct iterator *it);
+  void *(*get)(const struct iterator *it);
+  bool (*valid)(const struct iterator *it);
+};
+
+#define ITERATOR(p) ((struct iterator *)(p))
+
+/***
+  Advances the iterator to point to the next item in the sequence.
+***/
+static inline void iterator_next(struct iterator *it) {
+  if