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

Reply via email to