We have some places in code, where we have to cleanup, if an internal exception was thrown, e.g. after LOCK()ing a mutex or in classes/delegate.pmc to free the saved memory structure.

Attached is a test program with some macros allowing code like:

  TRY {
    some();
  }
  CATCH {
    clean_up();
    RETHROW;
  }

  some() {
    ...
    THROW(NULL_PMC_ACCESS);
  }

The actual implementation would need either an explicit Parrot_Interp argument or assume an C<interpreter> is around. malloc()/free() would be replaced by a free_list handling like in C<new_internal_exception>. On interpreter creation a few of these C<Parrot_exception>s would be created and put onto the C<interpreter->exc_free_list>.

Some questions:
- are these macros ok? (Yes I know - debugging :)
- Can the macro names interfer with existing ones?
- do we need an additional message text like now in internal_exception?

leo
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>

typedef struct e {
    jmp_buf dest;
    int err;
    struct e *prev;
} exc;

exc * exceptions;

#define TRY \
    do { \
        exc * ex = malloc(sizeof(*ex)); \
        ex->prev = exceptions; \
        exceptions = ex; \
        if (!setjmp(ex->dest))

#define CATCH \
    else

#define ENDTRY \
    } while(0); \
    do { \
        exc *e = exceptions; \
        exceptions = e->prev; \
        free(e); \
    } while(0)


#define THROW(e)  \
    do { \
        exceptions->err = e; \
        longjmp(exceptions->dest, 1); \
    } while(0)

#define RETHROW  \
    do { \
        exc *e = exceptions; \
        int er = e->err; \
        exceptions = e->prev; \
        free(e); \
        if (exceptions) \
            THROW(er); \
        else \
            puts("uncaught exception"); \
    } while(0)

void run(int e) {
    if (e == 1)
        THROW(1);
    else if (e == 2){
        TRY {
            run(e-1);
        }
        CATCH {
            puts("e2");
            RETHROW;
        }
        ENDTRY;
    }
}

int main(int argc, char *argv[])
{
    int i = 1;
    if (argc > 1)
        i = atoi(argv[1]);
    puts("S");
    TRY {
        run(i);
    }
    CATCH {
        puts("exception");
    }
    ENDTRY;
    puts("E");
    return 0;
}

Reply via email to