diff -pruN 0.7.2-1/debian/changelog 0.7.3+dfsg-1/debian/changelog --- 0.7.2-1/debian/changelog 2018-05-30 11:02:54.000000000 +0000 +++ 0.7.3+dfsg-1/debian/changelog 2018-06-14 08:40:03.000000000 +0000 @@ -1,3 +1,10 @@ +r-cran-later (0.7.3+dfsg-1) unstable; urgency=medium + + * New upstream version + * Remove autogenerated HTML docs since it is including compressed JS + + -- Andreas Tille Thu, 14 Jun 2018 10:40:03 +0200 + r-cran-later (0.7.2-1) unstable; urgency=medium * New upstream version diff -pruN 0.7.2-1/debian/copyright 0.7.3+dfsg-1/debian/copyright --- 0.7.2-1/debian/copyright 2018-05-30 11:02:54.000000000 +0000 +++ 0.7.3+dfsg-1/debian/copyright 2018-06-14 08:40:03.000000000 +0000 @@ -2,6 +2,7 @@ Format: https://www.debian.org/doc/packa Upstream-Name: later Upstream-Contact: Joe Cheng Source: https://cran.r-project.org/package=later +Files-Excluded: */inst/doc/*.html Files: * Copyright: 2015-2018 Joe Cheng, RStudio diff -pruN 0.7.2-1/debian/watch 0.7.3+dfsg-1/debian/watch --- 0.7.2-1/debian/watch 2018-05-30 11:02:54.000000000 +0000 +++ 0.7.3+dfsg-1/debian/watch 2018-06-14 08:40:03.000000000 +0000 @@ -1,2 +1,3 @@ version=4 +opts="repacksuffix=+dfsg,dversionmangle=s/\+dfsg[0-9]*//g,repack,compression=xz" \ https://cran.r-project.org/src/contrib/later_([-\d.]*)\.tar\.gz diff -pruN 0.7.2-1/DESCRIPTION 0.7.3+dfsg-1/DESCRIPTION --- 0.7.2-1/DESCRIPTION 2018-05-01 22:13:04.000000000 +0000 +++ 0.7.3+dfsg-1/DESCRIPTION 2018-06-08 21:42:57.000000000 +0000 @@ -1,7 +1,7 @@ Package: later Type: Package Title: Utilities for Delaying Function Execution -Version: 0.7.2 +Version: 0.7.3 Authors@R: c( person("Joe", "Cheng", role = c("aut", "cre"), email = "joe@rstudio.com"), person(family = "RStudio", role = "cph"), @@ -19,7 +19,7 @@ RoxygenNote: 6.0.1 Suggests: knitr, rmarkdown, testthat VignetteBuilder: knitr NeedsCompilation: yes -Packaged: 2018-05-01 18:50:54 UTC; jcheng +Packaged: 2018-06-08 17:43:59 UTC; jcheng Author: Joe Cheng [aut, cre], RStudio [cph], Marcus Geelnard [ctb, cph] (TinyCThread library, @@ -28,4 +28,4 @@ Author: Joe Cheng [aut, cre], https://tinycthread.github.io/) Maintainer: Joe Cheng Repository: CRAN -Date/Publication: 2018-05-01 22:13:04 UTC +Date/Publication: 2018-06-08 21:42:57 UTC diff -pruN 0.7.2-1/inst/doc/later-cpp.html 0.7.3+dfsg-1/inst/doc/later-cpp.html --- 0.7.2-1/inst/doc/later-cpp.html 2018-05-01 18:50:54.000000000 +0000 +++ 0.7.3+dfsg-1/inst/doc/later-cpp.html 1970-01-01 00:00:00.000000000 +0000 @@ -1,306 +0,0 @@ - - - - - -Using later from C++ - - - - - - - - - - - - - - - - - - -

Using later from C++

- -

You can call later::later from C++ code in your own packages, to cause your own C-style functions to be called back. This is safe to call from either the main R thread or a different thread; in both cases, your callback will be invoked from the main R thread.

- -

To use the C++ interface, you'll need to:

- -
    -
  • Add later to your DESCRIPTION file, under both LinkingTo and Imports
  • -
  • Make sure that your NAMESPACE file has an import(later) entry. If your package uses roxygen2, you can do this by adding the following lines to any file under R/: - -#' @import later -NULL -
  • -
  • Add #include <later_api.h> to the top of each C++ file that uses the below APIs.
  • -
- -

Executing a C function later

- -

The later::later function is accessible from later_api.h and its prototype looks like this:

- -
void later(void (*func)(void*), void* data, double secs)
-
- -

The first argument is a pointer to a function that takes one void* argument and returns void. The second argument is a void* that will be passed to the function when it's called back. And the third argument is the number of seconds to wait (at a minimum) before invoking. In all cases, the function will be invoked on the R thread, when no user R code is executing.

- -

Background tasks

- -

This package also offers a higher-level C++ helper class called later::BackgroundTask, to make it easier to execute tasks on a background thread. It takes care of launching the background thread for you, and returning control back to the R thread at a later point; you're responsible for providing the actual code that executes on the background thread, as well as code that executes on the R thread before and after the background task completes.

- -

Its public/protected interface looks like this:

- -
class BackgroundTask {
-
-public:
-  BackgroundTask();
-  virtual ~BackgroundTask();
-
-  // Start executing the task  
-  void begin();
-
-protected:
-  // The task to be executed on the background thread.
-  // Neither the R runtime nor any R data structures may be
-  // touched from the background thread; any values that need
-  // to be passed into or out of the Execute method must be
-  // included as fields on the Task subclass object.
-  virtual void execute() = 0;
-
-  // A short task that runs on the main R thread after the
-  // background task has completed. It's safe to access the
-  // R runtime and R data structures from here.
-  virtual void complete() = 0;
-}
-
- -

Create your own subclass, implementing a custom constructor plus the execute and complete methods.

- -

It's critical that the code in your execute method not mutate any R data structures, call any R code, or cause any R allocations, as it will execute in a background thread where such operations are unsafe. You can, however, perform such operations in the constructor (assuming you perform construction only from the main R thread) and complete method. Pass values between the constructor and methods using fields.

- -
#include <Rcpp.h>
-#include <later_api.h>
-
-class MyTask : public later::BackgroundTask {
-public:
-  MyTask(Rcpp::NumericVector vec) :
-    inputVals(Rcpp::as<std::vector<double> >(vec)) {
-  }
-
-protected:
-  void execute() {
-    double sum = 0;
-    for (std::vector<double>::const_iterator it = inputVals.begin();
-      it != inputVals.end();
-      it++) {
-
-      sum += *it;
-    }
-    result = sum / inputVals.size();
-  }
-
-  void complete() {
-    Rprintf("Result is %f\n", result);
-  }
-
-private:
-  std::vector<double> inputVals;
-  double result;
-};
-
- -

To run the task, new up your subclass and call begin(), e.g. (new MyTask(vec))->begin(). There's no need to keep track of the pointer; the task object will delete itself when the task is complete.

- -
// [[Rcpp::export]]
-void asyncMean(Rcpp::NumericVector data) {
-  (new MyTask(data))->begin();
-}
-
- -

It's not very useful to execute tasks on background threads if you can't get access to the results back in R. We'll soon be introducing a complementary R package that provides a suitable “promise” or “future” abstraction.

- - - - diff -pruN 0.7.2-1/MD5 0.7.3+dfsg-1/MD5 --- 0.7.2-1/MD5 2018-05-01 22:13:04.000000000 +0000 +++ 0.7.3+dfsg-1/MD5 2018-06-08 21:42:57.000000000 +0000 @@ -1,7 +1,7 @@ -ba8577a5645a5060a5aaa5646244e27c *DESCRIPTION +61d81b0658151dfca196f8ed709d9b44 *DESCRIPTION 75d68761a7804895a64b8af00fe03bf4 *LICENSE.note a61a4f9573261df4683af4d1bb0821b8 *NAMESPACE -64f741941c5dad552c2de804ba18d118 *NEWS.md +8c4ba8f678e7abcd3f3acdb93ee0c6b9 *NEWS.md fcda4768ebb5ff7e0497799b03721e69 *R/RcppExports.R e29ede24383cde06ab578cb3b8c843af *R/later.R ec0d146620f0a6071241098cb813b05c *README.md @@ -22,7 +22,8 @@ a59278879f048c7e7466b7bc55fa960c *man/ne 21c1284b2473b128389cc898bc2da2ad *src/callback_registry.h 01e40d134d7c438eb6495de2e627b715 *src/debug.h e37137a0533ebceaf32f5c75fa962804 *src/init.c -09b7308640f388a78740887f8b1d5fbc *src/later.cpp +56792fc6e11c596d958add3d2ce86743 *src/interrupt.h +c48e35ccdd1e5c33aa6100505cace605 *src/later.cpp 74456664b74c61e12794cdd833e205dd *src/later.h cf1eb8ffcf2851141d5ae9bb94a8481b *src/later_native.cpp 88299e56da452c82196fd4dc7a28afd2 *src/later_posix.cpp diff -pruN 0.7.2-1/NEWS.md 0.7.3+dfsg-1/NEWS.md --- 0.7.2-1/NEWS.md 2018-05-01 17:59:42.000000000 +0000 +++ 0.7.3+dfsg-1/NEWS.md 2018-06-08 17:42:30.000000000 +0000 @@ -1,3 +1,7 @@ +## later 0.7.3 + +* Fixed [issue #57](https://github.com/r-lib/later/issues/57): If a user interrupt occurred when later (internally) called `sys.nframe()`, the R process would crash. [PR #58](https://github.com/r-lib/later/pull/58) + ## later 0.7.2 * Fixed [issue #48](https://github.com/r-lib/later/issues/48): Occasional timedwait errors from later::run_now. Thanks, @vnijs! [PR #49](https://github.com/r-lib/later/pull/49) diff -pruN 0.7.2-1/src/interrupt.h 0.7.3+dfsg-1/src/interrupt.h --- 0.7.2-1/src/interrupt.h 1970-01-01 00:00:00.000000000 +0000 +++ 0.7.3+dfsg-1/src/interrupt.h 2018-06-08 17:43:59.000000000 +0000 @@ -0,0 +1,32 @@ +#ifndef _INTERRUPT_H_ +#define _INTERRUPT_H_ + +#ifdef _WIN32 + +#include +#undef TRUE +#undef FALSE + +#endif // _WIN32 + + +// Borrowed from https://github.com/wch/r-source/blob/a0a6b159/src/include/R_ext/GraphicsDevice.h#L843-L858 +#ifndef BEGIN_SUSPEND_INTERRUPTS +/* Macros for suspending interrupts */ +#define BEGIN_SUSPEND_INTERRUPTS do { \ + Rboolean __oldsusp__ = R_interrupts_suspended; \ + R_interrupts_suspended = TRUE; +#define END_SUSPEND_INTERRUPTS R_interrupts_suspended = __oldsusp__; \ + if (R_interrupts_pending && ! R_interrupts_suspended) \ + Rf_onintr(); \ +} while(0) + +#include +LibExtern Rboolean R_interrupts_suspended; +LibExtern int R_interrupts_pending; +extern void Rf_onintr(void); +LibExtern Rboolean mbcslocale; +#endif + + +#endif diff -pruN 0.7.2-1/src/later.cpp 0.7.3+dfsg-1/src/later.cpp --- 0.7.2-1/src/later.cpp 2018-05-01 18:50:55.000000000 +0000 +++ 0.7.3+dfsg-1/src/later.cpp 2018-06-08 17:43:59.000000000 +0000 @@ -4,6 +4,7 @@ #include "debug.h" #include "callback_registry.h" +#include "interrupt.h" // For debug.h #if defined(DEBUG_THREAD) @@ -30,22 +31,28 @@ public: }; // Returns number of frames on the call stack. Basically just a wrapper for -// base::sys.nframe(). +// base::sys.nframe(). Note that this can report that an error occurred if the +// user sends an interrupt while the `sys.nframe()` function is running. I +// believe that the only reason that it should set errorOccurred is because of +// a user interrupt. int sys_nframe() { ASSERT_MAIN_THREAD() SEXP e, result; int errorOccurred, value; - PROTECT(e = Rf_lang1(Rf_install("sys.nframe"))); - PROTECT(result = R_tryEval(e, R_BaseEnv, &errorOccurred)); + BEGIN_SUSPEND_INTERRUPTS { + PROTECT(e = Rf_lang1(Rf_install("sys.nframe"))); + PROTECT(result = R_tryEval(e, R_BaseEnv, &errorOccurred)); + + if (errorOccurred) { + value = -1; + } else { + value = INTEGER(result)[0]; + } - if (errorOccurred) { - value = -1; - } else { - value = INTEGER(result)[0]; - } + UNPROTECT(2); + } END_SUSPEND_INTERRUPTS; - UNPROTECT(2); return value; }