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 675024 - adds g_list_copy_deep() and g_slist_copy_deep
adds g_list_copy_deep() and g_slist_copy_deep
Status: RESOLVED FIXED
Product: glib
Classification: Platform
Component: general
unspecified
Other All
: Normal enhancement
: ---
Assigned To: gtkdev
gtkdev
Depends on:
Blocks:
 
 
Reported: 2012-04-28 16:34 UTC by Jonh Wendell
Modified: 2012-06-21 20:23 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Adds g_list_copy_deep() (4.00 KB, patch)
2012-04-28 16:34 UTC, Jonh Wendell
reviewed Details | Review
Adds g_slist_copy_deep() (4.05 KB, patch)
2012-04-28 16:35 UTC, Jonh Wendell
none Details | Review
patch v2 (8.29 KB, patch)
2012-06-21 15:28 UTC, Jonh Wendell
none Details | Review
patch v3 (9.66 KB, patch)
2012-06-21 19:15 UTC, Jonh Wendell
reviewed Details | Review

Description Jonh Wendell 2012-04-28 16:34:04 UTC
those functions makes a deep (full) copy of a list, in contrast with list_copy() which doesn't copy its elements data.
Comment 1 Jonh Wendell 2012-04-28 16:34:46 UTC
Created attachment 213026 [details] [review]
Adds g_list_copy_deep()
Comment 2 Jonh Wendell 2012-04-28 16:35:16 UTC
Created attachment 213027 [details] [review]
Adds g_slist_copy_deep()
Comment 3 Jonh Wendell 2012-06-20 15:55:27 UTC
ping
Comment 4 Colin Walters 2012-06-20 15:59:18 UTC
Seems like you could generalize this a bit as g_list_map().

But...what's the use case?  What code pattern requires you to deep copy lists?
Comment 5 Jonh Wendell 2012-06-20 16:07:27 UTC
suppose you have a list of gobjects and want a full duplicated list. so, you can pass g_object_ref.

at the time we had a little irc chat and derst liked the idea.
Comment 6 Colin Walters 2012-06-20 16:14:18 UTC
(In reply to comment #5)
> suppose you have a list of gobjects and want a full duplicated list.

The concrete question is - what projects would use this code, and where would they use it?  Presumably you have one?
Comment 7 Colin Walters 2012-06-20 16:15:58 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > suppose you have a list of gobjects and want a full duplicated list.
> 
> The concrete question is - what projects would use this code, and where would
> they use it?  

Also, just try running "git grep g_list_copy" in glib.  Looks like there's at least one potential user in gio/gunixvolumemonitor.c
Comment 8 Jonh Wendell 2012-06-20 16:21:55 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > suppose you have a list of gobjects and want a full duplicated list.
> 
> The concrete question is - what projects would use this code, and where would
> they use it?  Presumably you have one?

I'm using it in a proprietary software in my company. that's why I've cooked that patch. It seems useful for other people, and nice to have it in upstream for everyone consume.
Comment 9 Colin Walters 2012-06-20 16:31:47 UTC
(In reply to comment #8)
> (In reply to comment #6)
> > (In reply to comment #5)
> > > suppose you have a list of gobjects and want a full duplicated list.
> > 
> > The concrete question is - what projects would use this code, and where would
> > they use it?  Presumably you have one?
> 
> I'm using it in a proprietary software in my company. 

OK, but you could at least explain *why* you need to copy+ref a list.  Often for example if you don't need to mutate the list, passing around a GPtrArray that you just ref/unref is *significantly* more efficient.

> that's why I've cooked
> that patch. It seems useful for other people, and nice to have it in upstream
> for everyone consume.

But you need to at least add tests.  Finding a "real-world" user inside GLib or GNOME (like the gio/gunixvolumemonitor.c case I pointed out) also helps a lot in arguing for new API.
Comment 10 Jonh Wendell 2012-06-20 16:50:17 UTC
> OK, but you could at least explain *why* you need to copy+ref a list.  Often
> for example if you don't need to mutate the list, passing around a GPtrArray
> that you just ref/unref is *significantly* more efficient.

In my case, it's a multithread program, so, between the time I do the copy and the time I'll process the list, other thread might touch the list and its elements, doing an unref for instance.

> 
> > that's why I've cooked
> > that patch. It seems useful for other people, and nice to have it in upstream
> > for everyone consume.
> 
> But you need to at least add tests.  Finding a "real-world" user inside GLib or
> GNOME (like the gio/gunixvolumemonitor.c case I pointed out) also helps a lot
> in arguing for new API.

I've found some users like

clutter (clutter-master-clock.c):
  timelines = g_slist_copy (master_clock->timelines);
  g_slist_foreach (timelines, (GFunc) g_object_ref, NULL);

telepathy (connection-contact-info.c): tp_contact_info_spec_list_copy ()

gnome-shell (shell-polkit-authentication-agent.c)
  request->identities = g_list_copy (identities);
  g_list_foreach (request->identities, (GFunc) g_object_ref, NULL);

I stopped grepping...
Comment 11 Emmanuele Bassi (:ebassi) 2012-06-20 17:00:42 UTC
we use g_list_foreach(list, g_object_ref, NULL) in a couple of places where we iterate over a list because we need to guarantee that the list elements survive the end of the iteration - each iteration could change the list, or release a reference on the elements.

having a g_list_copy_deep() (I'm partial to g_list_copy_full() tho) would essentially remove one line, but after all we did that for g_list_free_full().
Comment 12 Colin Walters 2012-06-20 17:25:09 UTC
Review of attachment 213026 [details] [review]:

::: glib/glist.c
@@ +610,3 @@
+ *
+ * In contrast with g_list_copy(), this function does copy the actual data for
+ * each element in the list. It uses @func as a function that actually copies

How about:

"In contrast with g_list_copy(), this function uses @func to make a copy of each list element, in addition to copying the list container itself."

@@ +636,3 @@
+  GList *new_list = NULL;
+
+  if (list)

Might allow passing NULL for func too, then you could change g_list_copy() to just call g_list_copy_deep (list, NULL, NULL) and avoid the code duplication.
Comment 13 Colin Walters 2012-06-20 17:25:49 UTC
Review of attachment 213027 [details] [review]:

Can you fold these two patches together?  And add a link to the bug in the text description.  See:

https://live.gnome.org/GnomeLove/SubmittingPatches
Comment 14 Jonh Wendell 2012-06-21 15:28:09 UTC
Created attachment 216937 [details] [review]
patch v2
Comment 15 Colin Walters 2012-06-21 17:03:14 UTC
New patch looks fine except it's still lacking any test coverage.  Add one to glib/tests/list.c please.
Comment 16 Jonh Wendell 2012-06-21 19:15:48 UTC
Created attachment 216955 [details] [review]
patch v3
Comment 17 Colin Walters 2012-06-21 20:00:43 UTC
Review of attachment 216955 [details] [review]:

Some minor things, feel free to commit after adjustments.  Thanks for the patch!

::: glib/glist.h
@@ +82,3 @@
 					 GList            *link_) G_GNUC_WARN_UNUSED_RESULT;
 GList*   g_list_reverse                 (GList            *list) G_GNUC_WARN_UNUSED_RESULT;
 GList*   g_list_copy                    (GList            *list) G_GNUC_WARN_UNUSED_RESULT;

One thing I forgot before; this needs to be annotated GLIB_AVAILABLE_IN_2_34

::: glib/gslist.h
@@ +81,3 @@
 					  GSList           *link_) G_GNUC_WARN_UNUSED_RESULT;
 GSList*  g_slist_reverse                 (GSList           *list) G_GNUC_WARN_UNUSED_RESULT;
 GSList*  g_slist_copy                    (GSList           *list) G_GNUC_WARN_UNUSED_RESULT;

GLIB_AVAILABLE_IN_2_34

::: glib/tests/list.c
@@ +410,3 @@
+  for (u = l, v = l2; u && v; u = u->next, v = v->next)
+    {
+      g_assert (GPOINTER_TO_INT (u->data) * 2 == GPOINTER_TO_INT (v->data));

This is totally minor, but I'd use g_assert_cmpint() here, since it gives you better error messages.
Comment 18 Jonh Wendell 2012-06-21 20:23:10 UTC
thanks for your help, patch pushed.