Sean O'Rourke:
# On Tue, 28 May 2002, Jerome Vouillon wrote:
# > That's an interesting point, actually. What is the right
# thing to do
# > when we run out of memory?
# > - Abort immediately.
# > This is not very user-friendly.
# > - Return a special value.
# > But then we need to check the return value of almost all functions
# > (including string_compare, for instance).
#
# I personally dislike this approach, as it requires a large
# amount of programming discipline from everyone who works on
# the project. The current code indicates that if we took this
# approach, we would spend quite a bit of time squashing bugs
# from not checking return values in wierd places. It probably
# also hurts common-case performance to litter your code with
# redundant null-checks as well, but I don't have any data.
#
# > - Instead of returning a special value, we can set a global variable
# > to signal the error.
# > Again, we need to check this variable everywhere.
#
# This by itself seems worse than the above, since it makes
# problems even easier to ignore.
OTOH, if all C functions start with a boilerplate like:
if(interpreter->flags & PARROT_exception_FLAG) {
return NULL;
}
then this allows us to easily do things like:
string_concat(interpreter, string_concat(interpreter, a, b), c);
as long as we check for the exception immediately after. In fact, that
even lets you delay checking for exceptions so you can centralize
things--see below.
# > Note that this is the solution adopted by Java.
#
# Last time I wrote in Java, errors were entirely
# exception-based. Have things changed because of the locking
# issues you mention below?
I assume he means within the JVM's internals.
# > - Raise an exception using longjmp.
# > But then, if we start using locks all over the place like in Java,
# > we are pretty sure to leave the program in an inconsistent state.
#
# We're currently lock-free, which makes this sound like a good option.
I think we just have to say "if you put a lock on something, make sure
to set up an exception handler to unlock it and then rethrow the
exception".
I also think that any way you do it we'll have to wrap it in macros--at
least for embedders and extenders. If I ever find a few months of pure
boredom, I'd like to try to reimplement Parrot in C++, just to see how
much easier it would make things like PMCs; if we have appropriately set
up macros, we can hide from the user the actual implementation of
exceptions:
#define PARROT_TRY /* nothing */
#define PARROT_CATCH if(interpreter->flags &
PARROT_exception_FLAG)
...
PARROT_TRY {
d=string_concat(interpreter,
string_concat(interpreter, a, b), c);
...
}
PARROT_CATCH {
(code)
}
Just change the macros to:
#define PARROT_TRY try
#define PARROT_CATCH catch(void* PARROT_CATCH_this_is_unused)
for C++, or:
#define PARROT_TRY if(!setjmp())
#define PARROT_CATCH else
for setjmp/longjmp. (Yes, I know that's not the way setjmp is really
used, but you get the idea.) For short stretches of code, I'd imagine
that
PARROT_TRY d=string_concat(interpreter,
string_concat(interpreter, a, b), c)
PARROT_CATCH Parrot_fputs(interpreter, Parrot_stderr, "We're
screwed!");
(assuming that C++'s try and catch can take statements instead of
blocks, anyway--although even if they don't, it's just four more
characters.)
--Brent Dax <[EMAIL PROTECTED]>
@roles=map {"Parrot $_"} qw(embedding regexen Configure)
blink: Text blinks (alternates between visible and invisible).
Conforming user agents are not required to support this value.
--The W3C CSS-2 Specification