From schattenpflanze at arcor.de  Tue Apr 26 13:30:19 2011
From: schattenpflanze at arcor.de (schattenpflanze at arcor.de)
Date: Tue, 26 Apr 2011 13:30:19 +0200
Subject: [Rd] Interrupting C++ code execution
In-Reply-To: <201104252018.01541.thomas.friedrichsmeier@ruhr-uni-bochum.de>
References: <4DB53D47.7060903@arcor.de>
	<85607CA7-D76F-4210-9C6E-F3E9F26F7D0E@r-project.org>
	<F1EAEEC8-7828-403F-BF2D-10A4F925B4E6@r-project.org>
	<201104252018.01541.thomas.friedrichsmeier@ruhr-uni-bochum.de>
Message-ID: <4DB6ACCB.8050606@arcor.de>

I have tested the solutions suggested by Simon and Thomas on a Linux 
machine. These are my findings:

> On Windows you can look at the variable "UserBreak", available from
> Rembedded.h. Outside of Windows, you can look at R_interrupts_pending,
> available from R_ext/GraphicsDevice.h. R_ext/GraphicsDevice.h also has
> R_interrupts_suspended, which you may or may not want to take into account,
> depending on your use-case.
I did not manage to get this to work. Neither R_interrupts_pending nor 
R_interrupts_suspended seem to change when I press ctrl+c. Perhaps this 
is due to the fact that I run R in a terminal without any graphical 
interface?

> static void chkIntFn(void *dummy) {
>   R_CheckUserInterrupt();
> }
> // this will call the above in a top-level context so it won't longjmp-out of your context
> bool checkInterrupt() {
>   return (R_ToplevelExec(chkIntFn, NULL) == FALSE);
> }
> // your code somewhere ...
> if (checkInterrupt()) { // user interrupted ... }
This solution works perfectly! It takes slightly longer to call this 
function than the plan R_CheckUserInterrupt() call, but in any 
reasonable scenario, the additional time is absolutely insignificant.

Inside OpenMP parallel for constructs, one has to make sure that only 
the thread satisfying omp_get_thread_num()==0 makes the call (the 
'master' construct cannot be nested inside a loop). I can then set a 
flag, which is queried by every thread in every loop cycle, causing fast 
termination of the parallel loop. After the loop, I throw an exception. 
Thus, my code is terminated gracefully with minimal effort. I can do 
additional cleanup operations (which usually is not necessary, since I 
use smart pointers), and report details on the interrupt to the user.

With my limited testing, so far I have not noticed any downsides. Of 
course, there is the obvious drawback of not being supported officially 
(and thus maybe being subject to change), the question of portability, 
and the question of interoperability with other errors.

Moreover, I have found an old thread discussing almost the same topic:
http://tolstoy.newcastle.edu.au/R/e4/devel/08/05/1686.html .
The thread was created in 2008, so the issue is not really a new one. 
The solution proposed there is actually the same as the one suggested by 
Simon, namely using R_ToplevelExec().

An officially supported, portable solution would of course be much 
appreciated!


Best regards,
Peter



[Rd] Interrupting C++ code execution
schattenpflanze at arcor.de