After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 169285 - Add iterators to GTree
Add iterators to GTree
Status: RESOLVED DUPLICATE of bug 578873
Product: glib
Classification: Platform
Component: general
unspecified
Other Linux
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2005-03-05 12:26 UTC by Maurizio Monge
Modified: 2011-02-18 16:14 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
convert GTree to threaded tree (19.65 KB, patch)
2005-03-05 12:31 UTC, Maurizio Monge
none Details | Review
gtree.c rewritten (43.43 KB, text/plain)
2005-03-07 15:55 UTC, Maurizio Monge
  Details
gtree.h rewritten (5.48 KB, text/plain)
2005-03-07 15:57 UTC, Maurizio Monge
  Details
bench.c (small benchmark) (1.47 KB, text/plain)
2005-03-07 16:00 UTC, Maurizio Monge
  Details
gtree.c rewritten (45.63 KB, text/plain)
2005-03-08 07:46 UTC, Maurizio Monge
  Details
gtree.h rewritten (5.74 KB, text/plain)
2005-03-08 07:46 UTC, Maurizio Monge
  Details
gtree.c rewritten (44.41 KB, text/plain)
2005-03-08 13:41 UTC, Maurizio Monge
  Details
gtree.c rewritten (45.87 KB, text/plain)
2005-03-09 14:26 UTC, Maurizio Monge
  Details
gtree.h rewritten (6.01 KB, text/plain)
2005-03-09 14:27 UTC, Maurizio Monge
  Details
gtree.c rewritten and fixed :-) (46.17 KB, text/plain)
2005-05-16 02:45 UTC, Maurizio Monge
  Details
gtree.c ok (46.07 KB, text/plain)
2005-05-16 16:03 UTC, Maurizio Monge
  Details
convert to threaded tree without adding api (31.46 KB, patch)
2006-01-09 16:41 UTC, Matthias Clasen
committed Details | Review

Description Maurizio Monge 2005-03-05 12:26:01 UTC
It should be possible to modify a tree while you are traversiing the nodes.
With the patch i am submitting, GTree is converted to a threaded tree, that means
that the pointers of the leaf nodes instead of beeing null's point to next and
previous nodes (see http://www.stanford.edu/~blp/avl/libavl.html/Threads.html).
Nothing of what can be currently done with GTree is changed, with no API or ABI
change.
A new GTreeNode opaque structure is introduced to serve as iterator, and
iterators are never invalidated when an element is added, and if an element is
removed are invalidated only the iterators pointing to that element. 5 new
functions are introduced to work with iterators. The following is a code sample:

gconstpointer k,v;
GTreeNode *it,*it2;
it  = g_tree_find(tree,GINT_TO_POINTER (27),&k,&v,G_GREAT_EQ);
it2 = g_tree_find(tree,GINT_TO_POINTER (98),NULL,NULL,G_GREATER);
while(it && it!=it2)
{
  if( ((int)k) % 7 == 0)
  {
    gconstpointer oldk = k;
    it=g_tree_next(it,&k,&v);

    /* remove after incrementing the iterator */
    g_tree_remove(tree,oldk);
  }
  else
    it=g_tree_next(it,&k,&v);
}

I am marking the request as small feature, even if GTree are a bit
reworked and maybe it should be marked as medium feature.
I am submitting the patch in the next message.
Comment 1 Maurizio Monge 2005-03-05 12:31:56 UTC
Created attachment 38296 [details] [review]
convert GTree to threaded tree

This is a patch to glib 2.6.2 with my previous patches foreach_range and
clear_node applied. If you want a direct patch to 2.6.2 just tell me.
Comment 2 Maurizio Monge 2005-03-07 15:55:21 UTC
Created attachment 38371 [details]
gtree.c rewritten

Here is the c file of the rewritten implementation. 
I am not sending a diff because the source is quite different.
Comment 3 Maurizio Monge 2005-03-07 15:57:29 UTC
Created attachment 38372 [details]
gtree.h rewritten

Here is the header. Just replace glib-2.6.2/glib/gree.[ch] with the attached
files.
Comment 4 Maurizio Monge 2005-03-07 16:00:00 UTC
Created attachment 38373 [details]
bench.c (small benchmark)

This is a small benchmark.
Comment 5 Maurizio Monge 2005-03-08 07:46:04 UTC
Created attachment 38397 [details]
gtree.c rewritten

Update:

- balance is no more a bitfield, thus making the new code 
  3x faster then the old one.
- g_tree_height is now O(log n) istead then O(n) (!).
- added my name in the beginning.
- estetic changes to please the Glib team :-)
Comment 6 Maurizio Monge 2005-03-08 07:46:47 UTC
Created attachment 38398 [details]
gtree.h rewritten

Updated header.
Comment 7 Maurizio Monge 2005-03-08 09:35:42 UTC
Here is a sample using the latest code, much simpler.
the GTreeNode structure is exported, but only the 'key' 
member (read-only) and the 'value' member (read-write).
See gtree.h for how private members are protected.
Note that the code, instead of g_tree_remove, uses 
the new g_tree_remove_node that is quite faster because
doesn't have to call the comparison function.
Here is the code sample:

GTreeNode *it,*it2;
it  = g_tree_find_node(tree, GINT_TO_POINTER(27), G_GREAT_EQ);
it2 = g_tree_find_node(tree, GINT_TO_POINTER(98), G_GREATER);

while( it && it!=it2 )
{
  if( ((int)it->key) % 7 == 0)
    it = g_tree_remove_node( tree, it, FALSE );
  else
    it = g_tree_next_node( tree, it );
}
Comment 8 Maurizio Monge 2005-03-08 13:41:20 UTC
Created attachment 38413 [details]
gtree.c rewritten

- added a node counter in the GTree, so that
  g_tree_nnodes is now O(1).
- cleanup and remove some old functions.
- other very minor optimizations.
Comment 9 Maurizio Monge 2005-03-09 14:26:06 UTC
Created attachment 38456 [details]
gtree.c rewritten

- fixed a bug in g_tree_find_node
- added g_tree_steal_all.
- added g_tree_steal_node and made possible to
  g_tree_remove_node to return a reference to the
  previous node.
Comment 10 Maurizio Monge 2005-03-09 14:27:03 UTC
Created attachment 38457 [details]
gtree.h rewritten

and here is the header.
Comment 11 Maurizio Monge 2005-05-16 02:45:09 UTC
Created attachment 46471 [details]
gtree.c rewritten and fixed :-)

Argh!
I had to fix a majog bug in the remove node function!
It should be working now...
please note that this file is still relative to glib 2.6.3,
and doesn't apply cleanly to glib 2.6.4 (because of some __IA_
linker alias...)
Comment 12 Maurizio Monge 2005-05-16 16:03:48 UTC
Created attachment 46499 [details]
gtree.c ok

Ok, this is the fix applied to the right file and ok for 2.6.4 :-)
Comment 13 Matthias Clasen 2005-06-18 04:53:06 UTC
As Owen commented on irc, we would need a comprehensive set of GTree tests before
applying this patch.
Comment 14 Matthias Clasen 2005-06-23 20:48:09 UTC
Unlikely to make 2.8 at this point.
Comment 15 Matthias Clasen 2006-01-09 16:40:04 UTC
I have committed a bunch of additional tree tests to cvs HEAD now.

A number of comments on the patch:

1) I would like to see it split up into separate patches for
  a) converting gtree.c to a non-recursive threaded tree implementation
  b) adding new api (iterators, and related functions)

2) You can implement this without maintaining the node_type field. In every
  place where you access node_type, you also have the parent node around,
  so you can simple calculate the node_type information as
  parent->left == node.

3) Since the main advantage of threading is for in-order-iteration, shouldn't
  you patch g_tree_foreach to take advantage of it ? The patch below does that.

4) Some style things: 
  - put a space between if( 
  - indent opening { 
  - for the iterators, we don't normally do conditional struct definitions
    like that. Either make it opaque and add accessors for the public fields, 
    or expose all fields and mark the private ones by a /*< private >*/ comment.

I'll attach a patch for 1a) against cvs HEAD, that passes the new tests in tree-test.

Comment 16 Matthias Clasen 2006-01-09 16:41:33 UTC
Created attachment 57046 [details] [review]
convert to threaded tree without adding api
Comment 17 Matthias Clasen 2006-01-14 05:25:26 UTC
2006-01-14  Matthias Clasen  <mclasen@redhat.com>

	* glib/gtree.c: Replace the simple recursive implementation
	by a nonrecursive, threaded implementation by Maurizio 
	Monge.  (#169285)
Comment 18 Matthias Clasen 2006-01-14 05:27:58 UTC
Retitling to clarify whats left to do here.
Comment 19 Soren Sandmann Pedersen 2006-01-14 20:09:17 UTC
I didn't really review this, but I did glance over the patch, and to me it looks like g_tree_node_next() isn't quite correct: It assumes that the 'next' nodes will always be somewhere below the node, which is not true. A node with no children will have its parent as next for example, but g_tree_node() will return NULL in that case.
Comment 20 Matthias Clasen 2006-01-15 14:54:48 UTC
Soeren, its a threaded tree now, which means that next always
points to the next node if there is one.
Comment 21 Matthias Clasen 2010-07-10 06:18:24 UTC

*** This bug has been marked as a duplicate of bug 578873 ***