Browse thread
Wrapping sigsetjmps/siglongjmps in OCaml.
- Guillaume Yziquel
[
Home
]
[ Index:
by date
|
by threads
]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
[ Message by date: previous | next ] [ Message in thread: previous | next ] [ Thread: previous | next ]
Date: | 2009-11-30 (00:38) |
From: | Guillaume Yziquel <guillaume.yziquel@c...> |
Subject: | Wrapping sigsetjmps/siglongjmps in OCaml. |
Hello. I'm having some problems wrapping up the API for the R interpreter, namely because R seems to be using sigsetjmps and siglongjmps everywhere: that's how looping is implemented, for instance. (At least that's how I understand the source code). So I was wondering: what's the "best" way to wrap up such jumps in OCaml code? It may be that the jumps would happen in one single C function. Or it may be, due to a rather restrictive API for R, that I may have to reimplement some C code entirely in OCaml. In which case, the jumps would go over OCaml code. How would you deal with that? Here's the LONGJMP: SETJMP and LONGJMP are just macros to sigsetjmp and siglongjmp. > /* jumpfun - jump to the named context */ > > static void jumpfun(RCNTXT * cptr, int mask, SEXP val) > { > Rboolean savevis = R_Visible; > > /* run onexit/cend code for all contexts down to but not including > the jump target */ > PROTECT(val); > R_run_onexits(cptr); > UNPROTECT(1); > R_Visible = savevis; > > R_ReturnedValue = val; > R_GlobalContext = cptr; /* this used to be set to > cptr->nextcontext for non-toplevel > jumps (with the context set back at the > SETJMP for restarts). Changing this to > always using cptr as the new global > context should simplify some code and > perhaps allow loops to be handled with > fewer SETJMP's. LT */ > R_restore_globals(R_GlobalContext); > > LONGJMP(cptr->cjmpbuf, mask); > } Here's the SETJMP > SEXP applyClosure(SEXP call, SEXP op, SEXP arglist, SEXP rho, SEXP suppliedenv) > { > SEXP body, formals, actuals, savedrho; > volatile SEXP newrho; > SEXP f, a, tmp; > RCNTXT cntxt; > > /* formals = list of formal parameters */ > /* actuals = values to be bound to formals */ > /* arglist = the tagged list of arguments */ > > formals = FORMALS(op); > body = BODY(op); > savedrho = CLOENV(op); > > [...] > > /* Set a longjmp target which will catch any explicit returns > from the function body. */ > > if ((SETJMP(cntxt.cjmpbuf))) { > if (R_ReturnedValue == R_RestartToken) { > cntxt.callflag = CTXT_RETURN; /* turn restart off */ > R_ReturnedValue = R_NilValue; /* remove restart token */ > PROTECT(tmp = eval(body, newrho)); > } > else > PROTECT(tmp = R_ReturnedValue); > } > else { > PROTECT(tmp = eval(body, newrho)); > } > > endcontext(&cntxt); > > if (RDEBUG(op)) { > Rprintf("exiting from: "); > PrintValueRec(call, rho); > } > UNPROTECT(3); > return (tmp); > } All the best, -- Guillaume Yziquel http://yziquel.homelinux.org/