GError
- From: Owen Taylor <otaylor redhat com>
- To: gtk-devel-list gnome org
- Subject: GError
- Date: 22 Jun 2000 16:09:23 -0400
I went back and read through the GException thread:
http://mail.gnome.org/pipermail/gtk-devel-list/2000-February/002595.html
As well as the head article, see in particular Havoc's summary in:
http://mail.gnome.org/pipermail/gtk-devel-list/2000-February/002617.html
Out of the four possible schemes described in summary, I think the
reasonable ones are #1 and #4. (Havoc's original proposal and
return code + error object.)
Of those two, I agree with Havoc that the #1 is the more attractive
scheme, and think we should add it to GLib. As discussed in that thread,
we would rename the GException object to GError to make it clear that
this isn't some weird setjmp/longjmp non-local exit thingy.
The unresolved items in that thread were:
1) Should it be possible to have user-data in exceptions other than
the string.
The argument for would be that this is a feature of
many languages, (Java, C++, Python, etc.) and of CORBA. So it
must be useful, right? And there are a few cases where it is
genuinely useful. Probably the most common is location information
for a parse error to enable an editor to jump to the spot.
The argument against, is that people almost never use the feature
except to add explanatory strings:
- C++'s <stdexcept> has no data members other than explanatory strings.
- Python standard exceptions have line number for Syntax Error,
and errno for EnvironmentError, and no others.
- In a highly scientific survey, almost all exceptions in the Java
class libraries have no constructor arguments other than a string.
The fact that it _is_ even occasionally useful may be a fairly compelling
to add the feature - after all, trying to parse an error string
is a poor fallback.
Given that we want the ability to set user data, there are basically two
approaches:
a) Inheritance:
struct _GError
{
GQuark module;
gint error;
gchar *str;
GDestroyNotify notify;
};
struct _FooParseError
{
Error err;
int lineno;
}
The Foo library is responsible for allocating a full FooParseError structure,
filling in the fields, and setting notify appropriately.
int foo_parse_error_get_lineno (Error *err);
b) user_data.
struct _GError
{
GQuark module;
gint error;
gchar *str;
gpointer data;
GDestroyNotify notify;
};
GError *g_error_new_with_data (GQuark module, gint module, const gchar *str,
gpointer data, GDestroyNotify notify);
int foo_parse_error_get_lineno (Error *err);
a) is marginally more efficient, but given that GError is for error handling,
I think the increased encapsulation and simplicity of b) is worth that
overhead.
2) How are errors allocated. The simple scheme that I've discussed with Havoc
and I think works fine is that each module has a quark and an enumeration
of errors.
GError *err = NULL;
pixbuf = gdk_pixbuf_new_from_file (filename, &err);
if (!pixbuf)
{
if (g_error_matches (err, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT))
msgbox = gtk_message_show (GTK_MESSAGE_ERROR, parent, "Your hard drive is failing");
else
msgbox = gtk_message_show_error (parent, err);
g_error_free (err);
return;
}
If a module has more error types than fit in a single enumeration, than it could
use multiple quarks and multiple enumerations. (GDK_PIXBUF_LOAD_ERROR)
I think this setup will provide a nice standard way of reporting errors from
functions that can fail, and would like to see it in GLib-2.0.
Regards,
Owen
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]