0

I would like to use a threadsafe function pointer to be applied in an RcppPrallel worker. But I have already problems with this tiny example. No matter if I use it in a package and add SystemRequirements: C++11 in the DESCRIPTION file, or use it in a standard cpp file and add // [[Rcpp::plugins(cpp11)]] I get the same Errors: 'shared_ptr' is not a member of 'std'. Can anyone please help me? Thank you!

#include <Rcpp.h>
using namespace Rcpp;
using namespace std;


double f1 (double x, double y) {
   return x * y;
}

double f2 (double x, double y) {
   std::shared_ptr<int> p1;
   std::cout << "p1: " << p1.use_count() << '\n';
   return x + y;
}

typedef double (*funcPtr)(double x, double y);

std::shared_ptr<funcPtr> selectf(std::string abc) {

   std::shared_ptr<funcPtr> fp = NULL;

   if(abc == "a"){
      fp = std::make_shared<funcPtr>(new funcPtr(&f1));
   }else {
      fp = std::make_shared<funcPtr>(new funcPtr(&f2));
   }
   return fp;
}


// [[Rcpp::export]]
double f0(double x, double y, std::string abc){
   double ret;
   df = selectf(abc);
   ret = df(x, y);
   return(ret);
}


/*** R
if(FALSE){
   f0(10, 10, "a")
}
*/

System information:

> sessionInfo()
R version 3.5.0 (2018-04-23)
Platform: x86_64-w64-mingw32/x64 (64-bit)
Running under: Windows 7 x64 (build 7601) Service Pack 1

Matrix products: default

locale:
[1] LC_COLLATE=German_Germany.1252 
[2] LC_CTYPE=German_Germany.1252   
[3] LC_MONETARY=German_Germany.1252
[4] LC_NUMERIC=C                   
[5] LC_TIME=German_Germany.1252    

attached base packages:
[1] stats     graphics  grDevices utils     datasets 
[6] methods   base     

loaded via a namespace (and not attached):
 [1] compiler_3.5.0  R6_2.2.2        magrittr_1.5   
 [4] tools_3.5.0     withr_2.1.2     roxygen2_6.0.1 
 [7] yaml_2.1.19     memoise_1.1.0   Rcpp_0.12.18   
[10] xml2_1.2.0      stringi_1.2.2   stringr_1.3.1  
[13] digest_0.6.15   commonmark_1.5  devtools_1.13.5
Ralf Stubner
  • 26,263
  • 3
  • 40
  • 75
maxatSOflow
  • 269
  • 3
  • 10

2 Answers2

3

std::shared_ptr is declared in the header <memory>. Try:

#include <memory>

You can find the documentation for it here.

Bruce Collie
  • 435
  • 3
  • 8
  • Thanks. I tried it before, but when I use `#include ` and `// [[Rcpp::plugins(cpp11)]] ` at the same time in the header of the file my R session crashes with no further error message – maxatSOflow Jul 23 '18 at 14:41
  • 3
    Well that is different problem then. I see other errors in your code (no declaration for `df`), and maybe your use of function pointer is incorrect... – Dirk Eddelbuettel Jul 23 '18 at 14:42
  • Thank you! I also tried the toy example from [here](http://www.cplusplus.com/reference/memory/shared_ptr/shared_ptr/) and added `// [[Rcpp::export]]` to export the `main`, and had the same issues with R crashes. I use Rstudio 1.1.453. – maxatSOflow Jul 23 '18 at 15:03
3

The previous answer already told you about #include <memory>; in the follow-up you claim the basic example does not work -- it does for me.

But one clarification first: all memory management across calls to added (compiled) functions has to happen via R's memory management. That is what Rcpp does, and what Rcpp documents. Now, for multithreaded code we have RMatrix and RVector in RcppParalllel because we cannot interfere with R's memory management (and its single-threaded mode) from multithreaded code; see RcppParallel's excellent documentation for details.

That said, if you are sure you want shared_ptr within defined scope, you can. Here is a working copy based on the example you linked too.

Code

#include <memory>
#include <Rcpp.h>

// [[Rcpp::plugins(cpp11)]]

struct C { int* data; };

// [[Rcpp::export]]
bool foo() {
   std::shared_ptr<int> p1;
   std::shared_ptr<int> p2 (nullptr);
   std::shared_ptr<int> p3 (new int);
   std::shared_ptr<int> p4 (new int, std::default_delete<int>());
   std::shared_ptr<int> p5 (new int, [](int* p){delete p;}, std::allocator<int>());
   std::shared_ptr<int> p6 (p5);
   std::shared_ptr<int> p7 (std::move(p6));
   std::shared_ptr<int> p8 (std::unique_ptr<int>(new int));
   std::shared_ptr<C> obj (new C);
   std::shared_ptr<int> p9 (obj, obj->data);

   Rcpp::Rcout << "use_count:\n";
   Rcpp::Rcout << "p1: " << p1.use_count() << '\n';
   Rcpp::Rcout << "p2: " << p2.use_count() << '\n';
   Rcpp::Rcout << "p3: " << p3.use_count() << '\n';
   Rcpp::Rcout << "p4: " << p4.use_count() << '\n';
   Rcpp::Rcout << "p5: " << p5.use_count() << '\n';
   Rcpp::Rcout << "p6: " << p6.use_count() << '\n';
   Rcpp::Rcout << "p7: " << p7.use_count() << '\n';
   Rcpp::Rcout << "p8: " << p8.use_count() << '\n';
   Rcpp::Rcout << "p9: " << p9.use_count() << '\n';

   return true;
}

Use

R> Rcpp::sourceCpp("/tmp/soExample.cpp")
R> foo()
use_count:
p1: 0
p2: 0
p3: 1
p4: 1
p5: 2
p6: 0
p7: 2
p8: 1
p9: 2
[1] TRUE
R> 
Dirk Eddelbuettel
  • 360,940
  • 56
  • 644
  • 725
  • Thank you! Now the toy example works for me as well. I thought a shared pointer is exactly what I need for defining function pointers pointing all to the same function for each worker of a multithreaded process. I could not find an exampe in the Rcpp gallery where a fucntion pointer is passed to a worker. Would this be possibe or impossible due to your explanation above? Thank you. – maxatSOflow Jul 24 '18 at 16:24
  • Well you only wrote it did _not_ work for you so your writeup was incompleye and made other people (ie me) waste their time. Lesson: Write more complete and informative posts here. Lastly, there is a reason `shared_ptr` is not in the Rcpp Gallery, and that reason in my second paragraph above, and in the Writing R Extensions manual. It cannot work as you have to work primarily with R's memory management (where we use a different reference count). – Dirk Eddelbuettel Jul 24 '18 at 16:28
  • Thank you for your help. – maxatSOflow Jul 24 '18 at 16:37