Sean, On Apr 26, 2011, at 5:06 PM, Sean Robert McGuffee wrote:
> I've been thinking about how to handle c++ threads that were started via Rcpp > calls to some of my c++ libraries from R. My main obstacle is trying to make > sure that users don't try to process files that are being generated by a > thread before the thread finishes. One thing I am considering is having my > threaded code return a class to R that contains a pointer that it remembers. > Then maybe I could just change the value at that pointer when my thread > finishes. Does that seem like a reasonable approach? I'm not completely sure > if this is related to your issue or not, but it might be similar enough to be > worth asking... It depends. For a simple flag it's actually much more simple than that - you can create a boolean vector (make sure you preserve it) and just update its value when it's done - you don't even need an external pointer for that (if your'e careful). But the slight problem with that approach is rather that you don't have a way to tell R about the status change, so essentially you can only poll on the R side. A more proper way to deal with this is to use the event loop signaling to signal in R that the flag has changed. I'm working on a "threads" package that should help with that, but it's not complete yet (you can spawn threads from R and you can actually even synchronize them with R [so if the result is all you want it's there], but semaphores are not implemented yet --- your inquiry should shift it further up on my todo stack ;)). Cheers, Simon > > On 4/26/11 9:21 AM, "Simon Urbanek" <simon.urba...@r-project.org> wrote: > >> >> On Apr 26, 2011, at 7:30 AM, schattenpfla...@arcor.de wrote: >> >>> 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? >>> >> >> Thomas' suggestion was not aimed at your problem - it was sort of the inverse >> (more at your Qt question). If you want to interrupt R you can mess with >> those >> flags and them let R run the event loop. It doesn't work in your (original) >> case. >> >> >>>> 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), >> >> Actually, it is in the official API (Rinternals.h) so I don't think that is >> the issue. >> >> >>> the question of portability, and the question of interoperability with other >>> errors. >>> >> >> It is portable as well, so I'd say the main concern is what happens when >> events trigger something that is not related to you and you eat those errors. >> They will act as user-interrupt to you even if it's not what the user >> intended. One could argue that it's the lesser of the evils, because if you >> don't do anything R will just block so those events would have to wait until >> you're done anyway. >> >> >>> 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(). >>> >> >> Interesting - I'm glad Luke also suggested C-level onexit bac then - it is >> something I was thinking about before .. >> >> Cheers, >> Simon >> >> >>> An officially supported, portable solution would of course be much >>> appreciated! >>> >>> >>> Best regards, >>> Peter >>> >>> >> >> ______________________________________________ >> R-devel@r-project.org mailing list >> https://stat.ethz.ch/mailman/listinfo/r-devel > > > ______________________________________________ R-devel@r-project.org mailing list https://stat.ethz.ch/mailman/listinfo/r-devel