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
