GError



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]