#include
#include
#include "Rcpp.h"
[[cpp11::register]] void protect_one_(SEXP x, int n) {
for (R_xlen_t i = 0; i < n; ++i) {
PROTECT(x);
UNPROTECT(1);
}
}
[[cpp11::register]] void protect_one_sexp_(SEXP x, int n) {
for (R_xlen_t i = 0; i < n; ++i) {
cpp11::sexp y(x);
}
}
[[cpp11::register]] void protect_one_cpp11_(SEXP x, int n) {
for (R_xlen_t i = 0; i < n; ++i) {
SEXP p = cpp11::detail::store::insert(x);
cpp11::detail::store::release(p);
}
}
[[cpp11::register]] void protect_one_preserve_(SEXP x, int n) {
for (R_xlen_t i = 0; i < n; ++i) {
R_PreserveObject(x);
R_ReleaseObject(x);
}
}
// The internal protections here are actually uneeded, but it is a useful way to benchmark
// them
[[cpp11::register]] void protect_many_(int n) {
#ifdef CPP11_BENCH
std::vector res;
for (R_xlen_t i = 0; i < n; ++i) {
res.push_back(PROTECT(Rf_ScalarInteger(n)));
}
for (R_xlen_t i = n - 1; i >= 0; --i) {
SEXP x = res[i];
UNPROTECT(1);
res.pop_back();
}
#endif
}
[[cpp11::register]] void protect_many_cpp11_(int n) {
std::vector res;
for (R_xlen_t i = 0; i < n; ++i) {
res.push_back(cpp11::detail::store::insert(Rf_ScalarInteger(n)));
}
for (R_xlen_t i = n - 1; i >= 0; --i) {
SEXP x = res[i];
cpp11::detail::store::release(x);
res.pop_back();
}
}
[[cpp11::register]] void protect_many_sexp_(int n) {
std::vector res;
for (R_xlen_t i = 0; i < n; ++i) {
res.push_back(Rf_ScalarInteger(n));
}
for (R_xlen_t i = n - 1; i >= 0; --i) {
res.pop_back();
}
}
[[cpp11::register]] void protect_many_preserve_(int n) {
std::vector res;
for (R_xlen_t i = 0; i < n; ++i) {
SEXP x = Rf_ScalarInteger(n);
R_PreserveObject(x);
res.push_back(x);
}
for (R_xlen_t i = n - 1; i >= 0; --i) {
SEXP x = res[i];
R_ReleaseObject(x);
res.pop_back();
}
}
[[cpp11::register]] void protect_many_rcpp_(int n) {
#ifdef CPP11_BENCH
std::vector res;
for (R_xlen_t i = 0; i < n; ++i) {
res.push_back(Rcpp::RObject(Rf_ScalarInteger(n)));
}
for (R_xlen_t i = n - 1; i >= 0; --i) {
SEXP x = res[i];
res.pop_back();
}
#endif
}