Re: Behaviour of getters wrt dup/ref
On Fri, 14 Sep 2007, Alexander Larsson wrote: I got some feedback on gio about a getter function that returned a ref, and now I'm reviewing the gio APIs for things like that, making sure its internally consistent and consistent with gtk+/glib. However, I'm not sure what the gtk+ standard for this is. I heard no reffing getters, but that is somewhat limited. [without following the rest of this thread...] we discussed this back in the day when we still could have changed matters to be consistently across the platform. i believe the general getter/dup/peek discussion should be in the gnome-hackers archive around 2000. the short story is this: - it was suggested to name getters 'peek' if they returned pointers to memoery that was not duplicated or referenced. i.e. not owned by the caller. - it was suggested to name getters 'dup' (or 'ref') if they returned pointers to memoery that was allocated or referenced for the purpose of the getter, i.e. owned by the caller. - after a lengthy discussion, both suggestions got rejected and we stuck with: a) a getter is usually named '_get_' b) memory returned by a getter can be duplicated/referenced or not, that depends on the getter. the user always has to refer to the documentation or source code here. c) for strings, getters that return memory not owned by the caller should use G_CONST_RETURN. a good reason for why there is no simple convention for getters is the case of getting a list of objects. in some cases you'd want to be able to peek at the internally stored list nodes for performance reasons, e.g.: /* returned list *not* owed by caller */ GSList* gtk_window_peek_toplevels (void); free: /*noop*/ in others, you'd e.g. buy the overhead of a list copy for the sake of always returning doubly linked lists and do: /* returned list owed by caller, but not references */ GList* gtk_window_list_toplevels (void); free: g_list_free (return_value); and then again, for some object lists where it's common practice to modify or destroy some of the returned instances, or where it's likely to have a concurrent entity deleting/adding/shuffling items in the list, it may make most sense to hand out extra object references: /* returned list and additional references owed by caller */ GList* gtk_window_list_toplevels_refed (void); free: g_list_foreach (return_value, g_object_unref, NULL); g_list_free (return_value); --- ciaoTJ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
On Thu, 2007-09-20 at 13:37 +0200, Tim Janik wrote: On Fri, 14 Sep 2007, Alexander Larsson wrote: I got some feedback on gio about a getter function that returned a ref, and now I'm reviewing the gio APIs for things like that, making sure its internally consistent and consistent with gtk+/glib. However, I'm not sure what the gtk+ standard for this is. I heard no reffing getters, but that is somewhat limited. [without following the rest of this thread...] we discussed this back in the day when we still could have changed matters to be consistently across the platform. i believe the general getter/dup/peek discussion should be in the gnome-hackers archive around 2000. the short story is this: - it was suggested to name getters 'peek' if they returned pointers to memoery that was not duplicated or referenced. i.e. not owned by the caller. - it was suggested to name getters 'dup' (or 'ref') if they returned pointers to memoery that was allocated or referenced for the purpose of the getter, i.e. owned by the caller. - after a lengthy discussion, both suggestions got rejected and we stuck with: a) a getter is usually named '_get_' b) memory returned by a getter can be duplicated/referenced or not, that depends on the getter. the user always has to refer to the documentation or source code here. c) for strings, getters that return memory not owned by the caller should use G_CONST_RETURN. Makes sense to me. Thanks. ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
On Sat, 2007-09-15 at 23:08 -0400, Behdad Esfahbod wrote: On Fri, 2007-09-14 at 10:35 -0400, Alexander Larsson wrote: char * g_data_input_stream_get_line (GDataInputStream *data_stream, gsize *length, GCancellable *cancellable, GError **error); This actually reads new data from the stream, so it has to dup. One could imagine a similar call that returns some form of object instead of a string. Hi Alex, I think it's pretty common in glib and pango at least to return g_strdup'ed strings. The no-ref-count rule is mostly for objects that have a literal ref/unref pair. Ok, lets start from the general rule that strings are strdup:ed and gobjects are not ref:ed. Here are some violations of that in the gio api, reasons why, and possible changes: GList * g_app_info_get_all_for_type (const char *content_type); GAppInfo *g_app_info_get_default_for_type (const char *content_type); These obviously have to return a ref:ed value, because the content type string doesn't own the result. Maybe I should use another name for these. For instance g_app_info_query_all_fo_type and g_app_info_query_default_for_type. char * g_content_type_get_description (const char *type); char * g_content_type_get_mime_type (const char *type); GIcon * g_content_type_get_icon (const char *type); Same here. char *g_data_input_stream_get_line(...) Independent on the memory allocation properties of this it really should be read_line(). GDrive * g_volume_get_drive (GVolume *volume); This currently refs the result for historical reasons. This API is quite similar to the gnome-vfs volume manager API. There is a singleton volume monitor that keeps track of the volumes and drives availible on the system, which can change at any time. So, if you get the drive for a volume you get the current value, which might change later. In gnome-vfs this API is used by gnome-vfs backends, which means the API have to be threadsafe, and the only way to make it threadsafe is to ref in the getter. In gio we could decide to make this API not threadsafe and have non-reffing getters. Opinions on this? const char *g_file_info_get_attribute_string (GFileInfo *info, const char *attribute); and helpers like: const char *g_file_info_get_name (GFileInfo *info); For these calls it really makes no sense to dup the code. The GFileInfo is the container for the data, and we're just peeking at the data. This is somewhat similar to g_value_get_string() which also doesn't dup. GFile * g_file_get_parent (GFile *file); GFile * g_file_get_child (GFile *file, const char *name); These create a new GFile object, and there just is no way to not ref the return value. Should we use a different name for these, and if so what? I don't have any good ideas. Maybe just g_file_parent() / g_file_child()? GFileInfo *g_file_get_info (GFile *file, const char *attributes, GFileGetInfoFlagsflags, GCancellable*cancellable, GError **error); This is not really a getter, but an i/o operator (its stat/lstat). However, read_info() seems a bit weird name for this. Can anyone think of a better name? Other than that, for functions that return read data from the stream, some people may have reasons to want to avoid malloc/free'ing on each line. One way to work around that is to have the function take a GString, so you can reuse the buffer from the previous line. I know most people are not a big fan of that idea though. Hmmm, there are lots of lowlevel functions that you can use if you want to do fancy array growing and whatnot. get_line() (or better, read_line()) is mainly a very easy to use helper function for reading a full line of text. I don't think we want to make it more complicated, as then the whole point of it is sort of moot. ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
On Mon, 2007-09-17 at 11:57 +0200, Alexander Larsson wrote: char *g_data_input_stream_get_line(...) Independent on the memory allocation properties of this it really should be read_line(). GFileInfo *g_file_get_info (GFile *file, const char *attributes, GFileGetInfoFlagsflags, GCancellable*cancellable, GError **error); After some discussion on irc I decided that we at least should fix these two. So, i changed all the i/o get_XXX() calls in GDataInputStreams to be read_XXX(), and g_file_get_info() and related calls to g_file_query_info(). ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
On Sat, Sep 15, 2007 at 11:08:38PM -0400, Behdad Esfahbod wrote: On Fri, 2007-09-14 at 10:35 -0400, Alexander Larsson wrote: char * g_data_input_stream_get_line (GDataInputStream *data_stream, gsize *length, GCancellable *cancellable, GError **error); This actually reads new data from the stream, so it has to dup. One could imagine a similar call that returns some form of object instead of a string. I think it's pretty common in glib and pango at least to return g_strdup'ed strings. The no-ref-count rule is mostly for objects that have a literal ref/unref pair. Other than that, for functions that return read data from the stream, some people may have reasons to want to avoid malloc/free'ing on each line. One way to work around that is to have the function take a GString, so you can reuse the buffer from the previous line. I know most people are not a big fan of that idea though. The right interface for this type of functions have been already invented: that of glibc's getline. It can allocate new buffers, it can reuse existing buffers resizing them if necessary -- and it can be even used with GStrings [if they use the same memory allocator] although that's a bit dirty. Yeti -- http://gwyddion.net/ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
On Sun, 2007-09-16 at 03:03 -0400, David Nečas (Yeti) wrote: On Sat, Sep 15, 2007 at 11:08:38PM -0400, Behdad Esfahbod wrote: On Fri, 2007-09-14 at 10:35 -0400, Alexander Larsson wrote: char * g_data_input_stream_get_line (GDataInputStream *data_stream, gsize *length, GCancellable *cancellable, GError **error); This actually reads new data from the stream, so it has to dup. One could imagine a similar call that returns some form of object instead of a string. I think it's pretty common in glib and pango at least to return g_strdup'ed strings. The no-ref-count rule is mostly for objects that have a literal ref/unref pair. Other than that, for functions that return read data from the stream, some people may have reasons to want to avoid malloc/free'ing on each line. One way to work around that is to have the function take a GString, so you can reuse the buffer from the previous line. I know most people are not a big fan of that idea though. The right interface for this type of functions have been already invented: that of glibc's getline. It can allocate new buffers, it can reuse existing buffers resizing them if necessary -- and it can be even used with GStrings [if they use the same memory allocator] although that's a bit dirty. Well, that's exactly what happens if you make the API take GString. Yeti -- behdad http://behdad.org/ Those who would give up Essential Liberty to purchase a little Temporary Safety, deserve neither Liberty nor Safety. -- Benjamin Franklin, 1759 ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
On Sun, Sep 16, 2007 at 12:12:11PM -0400, Behdad Esfahbod wrote: The right interface for this type of functions have been already invented: that of glibc's getline. It can allocate new buffers, it can reuse existing buffers resizing them if necessary -- and it can be even used with GStrings [if they use the same memory allocator] although that's a bit dirty. Well, that's exactly what happens if you make the API take GString. I reacted to the remark that many people do not like having to pass a GString (perhaps understandably). The `decomposed GString' interface of getline() is then the next reasonable candidate. Yeti -- http://gwyddion.net/ ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
Am Sonntag, den 16.09.2007, 12:12 -0400 schrieb Behdad Esfahbod: On Sun, 2007-09-16 at 03:03 -0400, David Nečas (Yeti) wrote: On Sat, Sep 15, 2007 at 11:08:38PM -0400, Behdad Esfahbod wrote: On Fri, 2007-09-14 at 10:35 -0400, Alexander Larsson wrote: char * g_data_input_stream_get_line (GDataInputStream *data_stream, gsize *length, GCancellable *cancellable, GError **error); This actually reads new data from the stream, so it has to dup. One could imagine a similar call that returns some form of object instead of a string. I think it's pretty common in glib and pango at least to return g_strdup'ed strings. The no-ref-count rule is mostly for objects that have a literal ref/unref pair. Other than that, for functions that return read data from the stream, some people may have reasons to want to avoid malloc/free'ing on each line. One way to work around that is to have the function take a GString, so you can reuse the buffer from the previous line. I know most people are not a big fan of that idea though. The right interface for this type of functions have been already invented: that of glibc's getline. It can allocate new buffers, it can reuse existing buffers resizing them if necessary -- and it can be even used with GStrings [if they use the same memory allocator] although that's a bit dirty. Well, that's exactly what happens if you make the API take GString. Don't know if you try to support GString APIs, but I do not understand any GString bashing (expect maybe for the missing reference counting). In my opinion GString is a very useful member of the GLib API - so it also should be used in the public API of other libraries when it makes sense. Reading lines is such a place. A pattern I found useful for read_line like stuff is this: const gchar* maman_bar_read_line (MamanBar *self, GString *buffer) { g_size offset; g_return_val_if_fail (MAMAN_IS_BAR (self), NULL); if (NULL == buffer) { g_string_truncate (self-priv-buffer, 0); buffer = self-priv-buffer; } offset = buffer-len; manan_bar_real_read_line (self, buffer); return buffer-str + offset; } Sidenote to Alex: g_data_input_stream_get_line and its friend really should use read as verb, not get. The verb get usually indicates you do not change the state of an object - expect maybe for buffering expensive data. Ciao, Mathias -- Mathias Hasselmann [EMAIL PROTECTED] http://taschenorakel.de/ signature.asc Description: Dies ist ein digital signierter Nachrichtenteil ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
Hi Alex, Strange that nobody replied yet, so let's start discussion by dropping some random thoughts: For convenience and performance I consider returning a weak reference (const char*) the most reasonable choice for getters. If you want to keep a reference to the value returned longer than it is guaranteed to be valid, you still can call g_strdup on the caller side --- without putting any memory management overhead on callers which just want to have a short look on your properties. Well, but you raised the question for properties which have to be evaluated before returning them so for those properties I see two possibilities: 1) rename the methods from maman_get_bar to maman_eval_bar (or similiar) 2) handle them as lazy evaluated properties: const char* maman_get_expensive_info (Maman *self) { if (NULL == self-priv-expensive_info) self-priv-expensive_info = eval_expensive_info (); return self-priv-expensive_info; } Every time you know that property could become invalid you reset the _expensive_info field and of course you have to reset that field in your object's dispose method. IMHO this pattern is quite common in OOP and gives most convenience without sacrifing performance. Well, and if you think its reasonable to transfer ownership for that expensive field to the caller, you still can follow the pattern introduced by GValue: char* maman_steal_expensive_info (Maman *self) { char *result = maman_get_expensive_info (self); self-priv-expensive_info = NULL; return result; } Hope those thoughts help. Ciao, Mathias -- Mathias Hasselmann [EMAIL PROTECTED] http://taschenorakel.de/ signature.asc Description: Dies ist ein digital signierter Nachrichtenteil ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
Hi Alex, Strange that nobody replied yet, so let's start discussion by dropping some random thoughts: For convenience and performance I consider returning a weak reference (const char*) the most reasonable choice for getters. If you want to keep a reference to the value returned longer than it is guaranteed to be valid, you still can call g_strdup on the caller side --- without putting any memory management overhead on callers which just want to have a short look on your properties. Well, but you raised the question for properties which have to be evaluated before returning them so for those properties I see two possibilities: 1) rename the methods from maman_get_bar to maman_eval_bar (or similiar) 2) handle them as lazy evaluated properties: const char* maman_get_expensive_info (Maman *self) { if (NULL == self-priv-expensive_info) self-priv-expensive_info = eval_expensive_info (); return self-priv-expensive_info; } Every time you know that property could become invalid you reset the _expensive_info field and of course you have to reset that field in your object's dispose method. IMHO this pattern is quite common in OOP and gives most convenience without sacrifing performance. Well, and if you think its reasonable to transfer ownership for that expensive field to the caller, you still can follow the pattern introduced by GValue: char* maman_steal_expensive_info (Maman *self) { char *result = maman_get_expensive_info (self); self-priv-expensive_info = NULL; return result; } Hope those thoughts help. Ciao, Mathias -- Mathias Hasselmann [EMAIL PROTECTED] http://taschenorakel.de/ signature.asc Description: Dies ist ein digital signierter Nachrichtenteil ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list
Re: Behaviour of getters wrt dup/ref
On Fri, 2007-09-14 at 10:35 -0400, Alexander Larsson wrote: char * g_data_input_stream_get_line (GDataInputStream *data_stream, gsize *length, GCancellable *cancellable, GError **error); This actually reads new data from the stream, so it has to dup. One could imagine a similar call that returns some form of object instead of a string. Hi Alex, I think it's pretty common in glib and pango at least to return g_strdup'ed strings. The no-ref-count rule is mostly for objects that have a literal ref/unref pair. Other than that, for functions that return read data from the stream, some people may have reasons to want to avoid malloc/free'ing on each line. One way to work around that is to have the function take a GString, so you can reuse the buffer from the previous line. I know most people are not a big fan of that idea though. -- behdad http://behdad.org/ Those who would give up Essential Liberty to purchase a little Temporary Safety, deserve neither Liberty nor Safety. -- Benjamin Franklin, 1759 ___ gtk-devel-list mailing list gtk-devel-list@gnome.org http://mail.gnome.org/mailman/listinfo/gtk-devel-list