Register based error-handling?

Jonathan Marler via Digitalmars-d digitalmars-d at puremagic.com
Thu Nov 6 01:17:53 PST 2014


On Thursday, 6 November 2014 at 08:30:22 UTC, Ola Fosheim Grøstad 
wrote:
> It has been argued that exceptions are too slow in D to 
> propagate regular errors and should just be used for the truly 
> exceptional case. Then there should be a faster, but equally 
> convenient alternative for regular errors.
>
> In Go you "solve" the problem by returning tuples:
> (returnvalue,errorcode) = function_call();
>
> That is annoying. I'd rather see an implicit error code by 
> having "return error(value)" be a builtin.
>
>
> The basic idea is have a register based errno with language 
> support:
>
> 1. On amd64 you designate one "caller save" SIMD register to 
> error propagation.
>
> 2. Function signatures can specify if a return value:
> - never provide errors
> - provide errors that must be handled
> - provide errors that can be ignored
>
> 3. The language checks if all mandatory errors are handled.
>
> 4. Functions called are only allowed to write non-zero values 
> to the error register on return.
>
> The language then provide constructs for dealing with errors:
>
> // ignore error values, the compiler does not check
> // errors until after func2() is executed (like opengl)
>
> tryall {
>     value = func1();
>     value += func2();
> }
> catcherror{ … }
>
> value = func(3);
> if error { print_error(error); }
> // error is cleared here by the compiler
>
> value = func_optional_error();
>
> // error is cleared here before calling a function
> // that returns an error
>
> value = func4();

I've been in your shoes before, wondering why there aren't better 
mechanisms for error handling. I've changed my view over time and 
let me explain why.

First, D has the capability to generate code that uses error 
codes via registers or some global variable (note: I wouldn't 
specify that a compiler should use a certain register for error 
codes, the compiler is smart and will decide the best way to do 
that).  So I believe what you're looking for is a standard 
mechanism for functions to return errors and for the language to 
support that standard with a nice syntax.  I don't think this is 
a bad idea, but this isn't really necessary since you can already 
do these things, maybe in a more verbose syntax, but you can do 
them without modifying the current language.

One thing I like about your suggestion is you can specify if a 
function's error code should be verified to be handled at compile 
time.  It would be nice as a library writer if you could specify 
that the error MUST be handled by the caller.  That way you have 
some protection that users will use your functions correctly.

Now back to Exceptions. I wanted to address your concern (and 
everyone else's) about exceptions being "slow".  There are a lot 
of different opinions on this but over time I've "evolved" my 
view on them to some ideas that have been working for me for a 
while.  The first idea is when to throw an exception...easy

   A function should throw an exception if it CAN NOT perform the 
action indicated by it's name.

If a function named "write" fails to write, it should throw an 
exception.  So what about functions that want to return error 
codes instead.  What I do is prefix the function with "try".  You 
don't have to do that, but it helps me personally keep track of 
what functions require explicit error checking.  A function named 
"tryWrite" lets the user know the function may not write and they 
need to check somehow whether or not it failed.

Typically in the "normal operation" of a program, especially one 
you want designed to run fast, you will NEVER THROW AN EXCEPTION. 
  An exception being thrown isn't typically used as normal 
"control flow".  An exception is typically used to indicate an 
"environment error".  That's why it's OK that they are so slow 
and expensive.  You don't want to be throwing and catching 
exceptions all over the place, but when you do have an exception 
you want to capture as much info as possible even it if incurs a 
huge runtime cost.

A function that returns error in "normal program operation" 
should use the "try" mechanism and a function that always 
succeeds unless some type of environmental error occurs can just 
throw an exception.


More information about the Digitalmars-d mailing list