On Mon, Jul 29, 2013 at 5:32 PM, David Jeske <[email protected]> wrote:

> Unix + errno uses a zero return for success and non zero failure.
>
Yes. Exceptions also do this; either an exception is thrown or it is not.

> Functions which don't return errors today won't return errors tommorow.
>
Historically, this statement is incorrect. Also mispeled [?]  The reason it
was possible for this to change is that POSIX uses a side variable, *errno* for
error returns. That meant that every procedure *always* returned an error
value, but caller source code omitted the check when a procedure was not
documented to return errors, and callee source code generally (but not
reliably) left *errno* unmolested if the procedure was not documented to
possibly return errors.

*Because* this was the convention, the addition of necessary new ERRNO
values did, on occasion, break real code. There have even been examples of
client code that *relied* on procedures to leave *errno* alone if they
weren't documented to signal errors. Needless to say, such caller code
tended to be fragile.

> Return values are fast. This is my criteria a,b,c.
>
Yes, though I see no reason why this should *not* be true for exception
handlers when the Liskov implementation technique is used. Indeed, the
Liskov-style implementation should generally be faster, because (a) it is
equally fast in the exceptional return case, but (b) the exceptional return
case is rarely invoked, and (c) the exceptional return case doesn't get in
the way of normal return at the low-level data structure, and (d) being
designed into the language, a proper exception implementation doesn't
require the thread-local storage workarounds that are required for *errno*.

Exception return speed in C++ is complicated by the fact that essentially
every object has a destructor, so the compiler introduces an *appalling* number
of implicit catch blocks. In a managed language, implicit catch blocks only
get introduced around regions that may contain objects with finalizers,
which are comparatively rare.

We also need to be clear that the code associated with the catch blocks and
the catch demux/dispatch isn't counted against the exception mechanism,
because the same code would be necessary to respond to a non-zero error
result. The issues we are trading off are:

When returning an error code:

   - There is *always* an error return value that must be dispatched or
   propagated.
   - Returning both an error result and a procedure result simultaneously
   is syntactically awkward.
   - *Every* correct procedure return site *must* wrap the return with an
   error code check, if only to propagate the possible error. The total number
   of source lines of code is approximately doubled by this requirement, and a
   great many forward-not-taken (therefore mispredicted) branches are
   introduced into the code, with consequent maintenance errors and
   performance costs.

When raising an exception:

   - Usually no exception is raised. The raised exception case is - forgive
   me - exceptional.
   - Returning an actual procedure result is syntactically straightforward.
   - There are many correct procedure return sites that do *not* require
   wrapping, because exception propagation is handled by the out-of-band
   unwind code.

In short, *errno* isn't nearly as cheap as you think it is. Assuming a
properly implemented Liskov-style exception mechanism, it is *very* hard to
see how the *errno* mechanism can possibly be more efficient than exception
propagation.

> Expection systems which are not 100% declared/checked violate this, since
> a function which previously did not throw an exception could begin doing
> so.
>
Because *errno* is out of band, this is equally true in the POSIX scheme.

> Afaik, no such system exists which also affords runtime binding.
>
Perhaps not, but I'm unaware of any technical impediment that would
preclude doing so. So far as I know, exceptions will cross dynamic loading
points in C# and class loader boundaries in Java just fine.

The worst that happens in these situations is that you get a privately
declared exception type leaking out into a caller who doesn't know the type
of the particular exception. But the caller still knows that it *is* an
exception. While this is obviously bad hygiene, it's no worse than the
future proofing needed to guard against new future exceptions thrown by
existing callees.

Declared and checked exceptions have been tested in multiple languages. In
every case I know about they were abandoned because experience shows that
the cure is worse than the disease. This is true even when the declaration
is only done at module boundaries.


shap

<<360.gif>>

_______________________________________________
bitc-dev mailing list
[email protected]
http://www.coyotos.org/mailman/listinfo/bitc-dev

Reply via email to