void Exception_throw(const T *e, const char *func, const char *file, int line, const char *cause, ...) { assert(e); va_list ap; Exception_Frame *p = ThreadData_get(Exception_stack); if (p) { p->exception = e; p->func = func; p->file = file; p->line = line; if (cause) { va_start(ap, cause); vsnprintf(p->message, EXCEPTION_MESSAGE_LENGTH, cause, ap); va_end(ap); } pop_exception_stack; longjmp(p->env, Exception_thrown); } else if (cause) { char message[EXCEPTION_MESSAGE_LENGTH + 1] = "?"; va_start(ap, cause); vsnprintf(message, EXCEPTION_MESSAGE_LENGTH, cause, ap); va_end(ap); ABORT("%s: %s\n raised in %s at %s:%d\n", e->name, message, func ? func : "?", file ? file : "?", line); } else { ABORT("%s: 0x%p\n raised in %s at %s:%d\n", e->name, e, func ? func : "?", file ? file : "?", line); } }
//arena per thread - //the arena gets cleared between tasks. if your // task is not short lived, consider calling free once in a while Arena_T Oed_get_arena(void) { init_arena_once(); Arena_T arena = ThreadData_get(arena_td); if (!arena) { arena = Arena_new(); ThreadData_set(arena_td, arena); } return arena; }