diff --git a/ChangeLog b/ChangeLog index db5fefb66..dfce30f37 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,10 +1,37 @@ +2021-01-17 Iñaki Ucar + + * inst/include/Rcpp/String.h: Use Rcpp_{Preserve,Release}Object + throughout which connects to Rcpp_precious_* routines + * inst/include/Rcpp/exceptions.h: Use Rcpp_ReleaseObject + * inst/include/Rcpp/routines.h: Several corrections and refinements + * inst/include/Rcpp/storage/PreserveStorage.h: Ditto + * inst/include/Rcpp/traits/named_object.h: Ditto + * inst/include/Rcpp/unwuindProtect.h: Ditto + * inst/include/RcppCommon.h: Ditto + * src/barrier.cpp: Ditto + 2021-01-17 Dirk Eddelbuettel * DESCRIPTION (Version, Date): Roll minor version * inst/include/Rcpp/config.h: Idem + [ these were originally committed 17 May 2020 and have been rebased ] + * src/barrier.cpp: Implement Rcpp_precious_{init,teardown,preserve,remove} + * src/rcpp_init.c: Register cpp_precious_{init,teardown,preserve,remove} + and call from R_{init,unload}_Rcpp + * inst/include/Rcpp/routines.h: Declare Rcpp_precious_{init,teardown, + preserve,remove} + * inst/include/Rcpp/exceptions.h: Use Rcpp_precious_remove + * inst/include/Rcpp/traits/named_object.h: Use + Rcpp_precious_{preserve,remove} + * inst/include/Rcpp/unwuindProtect.h: Use Rcpp_precious_preserve + * inst/include/RcppCommon.h: Use Rcpp_precious_{preserve,remove} + 2021-01-16 Dirk Eddelbuettel + * DESCRIPTION (Version, Date): Roll minor version + * inst/include/Rcpp/config.h: Idem + * tests/tinytest.R: Test for CODECOV when deciding to run extensive tests or just a subset, and set CI=true to enable run full set diff --git a/DESCRIPTION b/DESCRIPTION index f4e9f579a..7e7531592 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: Rcpp Title: Seamless R and C++ Integration -Version: 1.0.6.1 +Version: 1.0.6.2 Date: 2021-01-17 Author: Dirk Eddelbuettel, Romain Francois, JJ Allaire, Kevin Ushey, Qiang Kou, Nathan Russell, Douglas Bates and John Chambers diff --git a/inst/include/Rcpp/String.h b/inst/include/Rcpp/String.h index 5a1401ffa..cff9b5e1f 100644 --- a/inst/include/Rcpp/String.h +++ b/inst/include/Rcpp/String.h @@ -1,8 +1,8 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- -// + // String.h: Rcpp R/C++ interface class library -- single string // -// Copyright (C) 2012 - 2018 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2012 - 2020 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar // // This file is part of Rcpp. // @@ -52,19 +52,19 @@ namespace Rcpp { typedef internal::const_string_proxy const_StringProxy; /** default constructor */ - String(): data(Rf_mkCharCE("", CE_UTF8)), buffer(), valid(true), buffer_ready(true), enc(CE_UTF8) { - Rcpp_PreserveObject(data); + String(): data(Rf_mkCharCE("", CE_UTF8)), token(R_NilValue), buffer(), valid(true), buffer_ready(true), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String()"); } /** copy constructor */ - String(const String& other) : data(other.get_sexp()), valid(true), buffer_ready(false), enc(Rf_getCharCE(other.get_sexp())) { - Rcpp_PreserveObject(data); + String(const String& other) : data(other.get_sexp()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(other.get_sexp())) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const String&)"); } /** construct a string from a single CHARSXP SEXP */ - String(SEXP charsxp) : data(R_NilValue) { + String(SEXP charsxp) : data(R_NilValue), token(R_NilValue) { if (TYPEOF(charsxp) == STRSXP) { data = STRING_ELT(charsxp, 0); } else if (TYPEOF(charsxp) == CHARSXP) { @@ -82,30 +82,30 @@ namespace Rcpp { valid = true; buffer_ready = false; enc = Rf_getCharCE(data); - Rcpp_PreserveObject(data); + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(SEXP)"); } /** from string proxy */ - String(const StringProxy& proxy): data(proxy.get()), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { - Rcpp_PreserveObject(data); + String(const StringProxy& proxy): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const StringProxy&)"); } - String(const StringProxy& proxy, cetype_t enc): data(proxy.get()), valid(true), buffer_ready(false) { - Rcpp_PreserveObject(data); + String(const StringProxy& proxy, cetype_t enc): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false) { + token = Rcpp_PreserveObject(data); set_encoding(enc); RCPP_STRING_DEBUG("String(const StringProxy&, cetype_t)"); } /** from string proxy */ - String(const const_StringProxy& proxy): data(proxy.get()), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { - Rcpp_PreserveObject(data); + String(const const_StringProxy& proxy): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false), enc(Rf_getCharCE(proxy.get())) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const const_StringProxy&)"); } - String(const const_StringProxy& proxy, cetype_t enc): data(proxy.get()), valid(true), buffer_ready(false) { - Rcpp_PreserveObject(data); + String(const const_StringProxy& proxy, cetype_t enc): data(proxy.get()), token(R_NilValue), valid(true), buffer_ready(false) { + token = Rcpp_PreserveObject(data); set_encoding(enc); RCPP_STRING_DEBUG("String(const const_StringProxy&, cetype_t)"); } @@ -113,53 +113,142 @@ namespace Rcpp { /** from a std::string */ String(const std::string& s, cetype_t enc = CE_UTF8) : buffer(s), valid(false), buffer_ready(true), enc(enc) { data = R_NilValue; + token = R_NilValue; RCPP_STRING_DEBUG("String(const std::string&, cetype_t)"); } - String(const std::wstring& s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), valid(true), buffer_ready(false), enc(enc) { - Rcpp_PreserveObject(data); + String(const std::wstring& s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), token(R_NilValue), valid(true), buffer_ready(false), enc(enc) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const std::wstring&, cetype_t)"); } /** from a const char* */ String(const char* s, cetype_t enc = CE_UTF8) : buffer(s), valid(false), buffer_ready(true), enc(enc) { data = R_NilValue; + token = R_NilValue; RCPP_STRING_DEBUG("String(const char*, cetype_t)"); } - String(const wchar_t* s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), valid(true), buffer_ready(false), enc(enc) { - Rcpp_PreserveObject(data); + String(const wchar_t* s, cetype_t enc = CE_UTF8) : data(internal::make_charsexp(s)), token(R_NilValue), valid(true), buffer_ready(false), enc(enc) { + token = Rcpp_PreserveObject(data); RCPP_STRING_DEBUG("String(const wchar_t* s, cetype_t)"); } /** constructors from R primitives */ - String(int x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(double x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(bool x) : data(internal::r_coerce(x)), valid(true) , buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(Rcomplex x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} - String(Rbyte x) : data(internal::r_coerce(x)), valid(true), buffer_ready(false), enc(CE_UTF8) {Rcpp_PreserveObject(data);} + String(int x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(double x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(bool x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true) , buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(Rcomplex x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } + String(Rbyte x) : data(internal::r_coerce(x)), token(R_NilValue), valid(true), buffer_ready(false), enc(CE_UTF8) { + token = Rcpp_PreserveObject(data); + } ~String() { - Rcpp_ReleaseObject(data); + Rcpp_ReleaseObject(token); data = R_NilValue; + token = R_NilValue; } - inline String& operator=(int x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(double x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(Rbyte x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(bool x ) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(Rcomplex x) { data = Rcpp_ReplaceObject(data, internal::r_coerce(x)); valid = true; buffer_ready = false; return *this; } - inline String& operator=(SEXP x) { data = Rcpp_ReplaceObject(data, x); valid = true; buffer_ready = false; return *this; } - inline String& operator=(const StringProxy& proxy) { data = Rcpp_ReplaceObject(data, proxy.get()); valid = true; buffer_ready=false; return *this; } - inline String& operator=(const String& other) { data = Rcpp_ReplaceObject(data, other.get_sexp()); valid = true; buffer_ready = false; return *this; } - inline String& operator=(const std::string& s) { buffer = s; valid = false; buffer_ready = true; return *this; } - inline String& operator=(const char* s) { buffer = s; valid = false; buffer_ready = true; return *this; } + inline String& operator=(int x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(double x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(Rbyte x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(bool x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(Rcomplex x) { + data = internal::r_coerce(x); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(SEXP x) { + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + } + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(const StringProxy& proxy) { + SEXP x = proxy.get(); + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(x); + } + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(const String& other) { + SEXP x = other.get_sexp(); + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(x); + } + valid = true; + buffer_ready = false; + return *this; + } + inline String& operator=(const std::string& s) { + buffer = s; + valid = false; + buffer_ready = true; + return *this; + } + inline String& operator=(const char* s) { + buffer = s; + valid = false; + buffer_ready = true; + return *this; + } private: template inline String& assign_wide_string(const T& s) { - data = Rcpp_ReplaceObject(data, internal::make_charsexp(s)); + data = internal::make_charsexp(s); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); valid = true; buffer_ready = false; return *this; @@ -191,7 +280,9 @@ namespace Rcpp { const char* buf = CHAR(data); std::wstring tmp(buf, buf + strlen(buf)); tmp += s; - data = Rcpp_ReplaceObject(data, internal::make_charsexp(tmp)); + data = internal::make_charsexp(tmp); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); valid = true; buffer_ready = false; return *this; @@ -205,7 +296,14 @@ namespace Rcpp { inline String& operator+=(const String& other) { RCPP_STRING_DEBUG("String::operator+=(const char*)"); if (is_na()) return *this; - if (other.is_na()) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this; } + if (other.is_na()) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += other; valid = false; return *this; } @@ -213,7 +311,14 @@ namespace Rcpp { RCPP_STRING_DEBUG("String::operator+=(const StringProxy&)"); if (is_na()) return *this; SEXP proxy_sexp = proxy; - if (proxy_sexp == NA_STRING) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this;} + if (proxy_sexp == NA_STRING) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += CHAR(proxy_sexp); valid = false; return *this; } @@ -221,14 +326,28 @@ namespace Rcpp { RCPP_STRING_DEBUG("String::operator+=(const StringProxy&)"); if (is_na()) return *this; SEXP proxy_sexp = proxy; - if (proxy_sexp == NA_STRING) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this;} + if (proxy_sexp == NA_STRING) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += CHAR(proxy_sexp); valid = false; return *this; } inline String& operator+=(SEXP x) { RCPP_STRING_DEBUG("String::operator+=(SEXP)"); if (is_na()) return *this; - if (x == NA_STRING) { data = Rcpp_ReplaceObject(data, NA_STRING); valid = true; buffer_ready = false; return *this;} + if (x == NA_STRING) { + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; + return *this; + } setBuffer(); buffer += CHAR(x); valid = false; return *this; } @@ -359,8 +478,11 @@ namespace Rcpp { inline void set_na() { - data = Rcpp_ReplaceObject(data, NA_STRING); - valid = true; buffer_ready = false; + data = NA_STRING; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + valid = true; + buffer_ready = false; } @@ -410,10 +532,12 @@ namespace Rcpp { if (valid) { // TODO: may longjmp on failure to translate? const char* translated = Rf_translateCharUTF8(data); - data = Rcpp_ReplaceObject(data, Rf_mkCharCE(translated, encoding)); + data = Rf_mkCharCE(translated, encoding); + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); } else { data = get_sexp_impl(); - Rcpp_PreserveObject(data); + token = Rcpp_PreserveObject(data); valid = true; } } @@ -461,6 +585,7 @@ namespace Rcpp { /** the CHARSXP this String encapsulates */ SEXP data; + SEXP token; /** a buffer used to do string operations withough going back to the SEXP */ std::string buffer; @@ -485,7 +610,7 @@ namespace Rcpp { RCPP_STRING_DEBUG("setData"); if (!valid) { data = get_sexp_impl(); - Rcpp_PreserveObject(data); + token = Rcpp_PreserveObject(data); valid = true; } } diff --git a/inst/include/Rcpp/config.h b/inst/include/Rcpp/config.h index aaa4ae277..277893503 100644 --- a/inst/include/Rcpp/config.h +++ b/inst/include/Rcpp/config.h @@ -30,7 +30,7 @@ #define RCPP_VERSION_STRING "1.0.6" // the current source snapshot -#define RCPP_DEV_VERSION RcppDevVersion(1,0,6,1) -#define RCPP_DEV_VERSION_STRING "1.0.6.1" +#define RCPP_DEV_VERSION RcppDevVersion(1,0,6,2) +#define RCPP_DEV_VERSION_STRING "1.0.6.2" #endif diff --git a/inst/include/Rcpp/exceptions.h b/inst/include/Rcpp/exceptions.h index 91e1f4b62..6e0774482 100644 --- a/inst/include/Rcpp/exceptions.h +++ b/inst/include/Rcpp/exceptions.h @@ -2,6 +2,7 @@ // exceptions.h: Rcpp R/C++ interface class library -- exceptions // // Copyright (C) 2010 - 2020 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2021 - 2020 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar // // This file is part of Rcpp. // diff --git a/inst/include/Rcpp/routines.h b/inst/include/Rcpp/routines.h index 437e42aee..8786fb26d 100644 --- a/inst/include/Rcpp/routines.h +++ b/inst/include/Rcpp/routines.h @@ -1,7 +1,9 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- + +// routines.h: Rcpp R/C++ interface class library -- callable function setup // -// Copyright (C) 2013 Romain Francois -// Copyright (C) 2015 Dirk Eddelbuettel +// Copyright (C) 2013 - 2014 Romain Francois +// Copyright (C) 2015 - 2020 Romain Francois and Dirk Eddelbuettel +// Copyright (C) 2021 Romain Francois, Dirk Eddelbuettel and Iñaki Ucar // // This file is part of Rcpp. // @@ -38,6 +40,11 @@ namespace Rcpp{ } double mktime00(struct tm &); struct tm * gmtime_(const time_t * const); + + void Rcpp_precious_init(); + void Rcpp_precious_teardown(); + SEXP Rcpp_precious_preserve(SEXP object); + void Rcpp_precious_remove(SEXP token); } SEXP rcpp_get_stack_trace(); @@ -127,6 +134,27 @@ namespace Rcpp { return fun(x); } + inline attribute_hidden void Rcpp_precious_init() { + typedef void (*Fun)(void); + static Fun fun = GET_CALLABLE("Rcpp_precious_init"); + fun(); + } + inline attribute_hidden void Rcpp_precious_teardown() { + typedef void (*Fun)(void); + static Fun fun = GET_CALLABLE("Rcpp_precious_teardown"); + fun(); + } + inline attribute_hidden SEXP Rcpp_precious_preserve(SEXP object) { + typedef SEXP (*Fun)(SEXP); + static Fun fun = GET_CALLABLE("Rcpp_precious_preserve"); + return fun(object); + } + inline attribute_hidden void Rcpp_precious_remove(SEXP token) { + typedef void (*Fun)(SEXP); + static Fun fun = GET_CALLABLE("Rcpp_precious_remove"); + fun(token); + } + } // The 'attribute_hidden' used here is a simple precessor defined from diff --git a/inst/include/Rcpp/storage/PreserveStorage.h b/inst/include/Rcpp/storage/PreserveStorage.h index be8d0fdab..7d069eeb1 100644 --- a/inst/include/Rcpp/storage/PreserveStorage.h +++ b/inst/include/Rcpp/storage/PreserveStorage.h @@ -1,3 +1,24 @@ + +// PreserveStorage.h: Rcpp R/C++ interface class library -- helper class +// +// Copyright (C) 2013 - 2020 Romain Francois +// Copyright (C) 2021 Romain Francois and Iñaki Ucar +// +// This file is part of Rcpp. +// +// Rcpp is free software: you can redistribute it and/or modify it +// under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 2 of the License, or +// (at your option) any later version. +// +// Rcpp is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Rcpp. If not, see . + #ifndef Rcpp_PreserveStorage_h #define Rcpp_PreserveStorage_h @@ -7,15 +28,20 @@ namespace Rcpp{ class PreserveStorage { public: - PreserveStorage() : data(R_NilValue){} + PreserveStorage() : data(R_NilValue), token(R_NilValue){} ~PreserveStorage(){ - Rcpp_ReleaseObject(data) ; + Rcpp_ReleaseObject(token) ; data = R_NilValue; + token = R_NilValue; } inline void set__(SEXP x){ - data = Rcpp_ReplaceObject(data, x) ; + if (data != x) { + data = x; + Rcpp_ReleaseObject(token); + token = Rcpp_PreserveObject(data); + } // calls the update method of CLASS // this is where to react to changes in the underlying SEXP @@ -28,7 +54,9 @@ namespace Rcpp{ inline SEXP invalidate__(){ SEXP out = data ; + Rcpp_ReleaseObject(token); data = R_NilValue ; + token = R_NilValue ; return out ; } @@ -48,6 +76,7 @@ namespace Rcpp{ private: SEXP data ; + SEXP token ; } ; } diff --git a/inst/include/Rcpp/traits/named_object.h b/inst/include/Rcpp/traits/named_object.h index 761ac24de..188c03742 100644 --- a/inst/include/Rcpp/traits/named_object.h +++ b/inst/include/Rcpp/traits/named_object.h @@ -1,9 +1,8 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- -/* :tabSize=4:indentSize=4:noTabs=false:folding=explicit:collapseFolds=1: */ -// + // named_object.h: Rcpp R/C++ interface class library -- named SEXP // -// Copyright (C) 2010 - 2017 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2010 - 2020 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar // // This file is part of Rcpp. // @@ -41,19 +40,22 @@ template class named_object { template <> class named_object { public: // #nocov start named_object( const std::string& name_, const SEXP& o_): - name(name_), object(o_) { - R_PreserveObject(object); + name(name_), object(o_), token(R_NilValue) { + token = Rcpp_precious_preserve(object); } named_object( const named_object& other ) : - name(other.name), object(other.object) { - R_PreserveObject(object); + name(other.name), object(other.object), token(other.token) { + token = Rcpp_precious_preserve(object); } ~named_object() { - R_ReleaseObject(object); + Rcpp_precious_remove(token); + } // #nocov end const std::string& name; SEXP object; +private: + SEXP token; }; diff --git a/inst/include/Rcpp/unwindProtect.h b/inst/include/Rcpp/unwindProtect.h index 7944aab81..ce6706842 100644 --- a/inst/include/Rcpp/unwindProtect.h +++ b/inst/include/Rcpp/unwindProtect.h @@ -1,6 +1,8 @@ + // unwind.h: Rcpp R/C++ interface class library -- Unwind Protect // -// Copyright (C) 2018 RStudio +// Copyright (C) 2018 - 2020 RStudio +// Copyright (C) 2021 RStudio, Dirk Eddelbuettel and Iñaki Ucar // // This file is part of Rcpp. // diff --git a/inst/include/RcppCommon.h b/inst/include/RcppCommon.h index 41ecce70d..fbaeaf8e9 100644 --- a/inst/include/RcppCommon.h +++ b/inst/include/RcppCommon.h @@ -1,9 +1,10 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- + // // RcppCommon.h: Rcpp R/C++ interface class library -- common include and defines statements // // Copyright (C) 2008 - 2009 Dirk Eddelbuettel -// Copyright (C) 2009 - 2017 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2009 - 2020 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar // // This file is part of Rcpp. // @@ -77,6 +78,9 @@ namespace Rcpp { SEXP Rcpp_fast_eval(SEXP expr_, SEXP env); SEXP Rcpp_eval(SEXP expr_, SEXP env = R_GlobalEnv); + SEXP Rcpp_precious_preserve(SEXP object); + void Rcpp_precious_remove(SEXP token); + namespace internal { SEXP Rcpp_eval_impl(SEXP expr, SEXP env); } @@ -87,28 +91,12 @@ namespace Rcpp { template class named_object; } - inline SEXP Rcpp_PreserveObject(SEXP x) { - if (x != R_NilValue) { - R_PreserveObject(x); - } - return x; - } - - inline void Rcpp_ReleaseObject(SEXP x) { - if (x != R_NilValue) { - R_ReleaseObject(x); - } + inline SEXP Rcpp_PreserveObject(SEXP object) { + return Rcpp_precious_preserve(object); } - inline SEXP Rcpp_ReplaceObject(SEXP x, SEXP y) { - - // if we are setting to the same SEXP as we already have, do nothing - if (x != y) { - Rcpp_ReleaseObject(x); - Rcpp_PreserveObject(y); - } - - return y; + inline void Rcpp_ReleaseObject(SEXP token) { + Rcpp_precious_remove(token); } } diff --git a/src/barrier.cpp b/src/barrier.cpp index 86b05e97e..11e2fa646 100644 --- a/src/barrier.cpp +++ b/src/barrier.cpp @@ -1,8 +1,8 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; tab-width: 4 -*- -// + // barrier.cpp: Rcpp R/C++ interface class library -- write barrier // -// Copyright (C) 2010 - 2019 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2010 - 2020 Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2021 Dirk Eddelbuettel, Romain Francois and Iñaki Ucar // // This file is part of Rcpp. // @@ -88,6 +88,46 @@ static SEXP Rcpp_cache = R_NilValue; #define RCPP_HASH_CACHE_INITIAL_SIZE 1024 #endif +namespace Rcpp { +static SEXP Rcpp_precious = R_NilValue; +// [[Rcpp::register]] +void Rcpp_precious_init() { + Rcpp_precious = CONS(R_NilValue, R_NilValue); // set up + R_PreserveObject(Rcpp_precious); // and protect +} +// [[Rcpp::register]] +void Rcpp_precious_teardown() { + R_ReleaseObject(Rcpp_precious); // release resource +} +// [[Rcpp::register]] +SEXP Rcpp_precious_preserve(SEXP object) { + if (object == R_NilValue) { + return R_NilValue; + } + PROTECT(object); + SEXP cell = PROTECT(CONS(Rcpp_precious, CDR(Rcpp_precious))); + SET_TAG(cell, object); + SETCDR(Rcpp_precious, cell); + if (CDR(cell) != R_NilValue) { + SETCAR(CDR(cell), cell); + } + UNPROTECT(2); + return cell; +} +// [[Rcpp::register]] +void Rcpp_precious_remove(SEXP token) { + if (token == R_NilValue) { + return; + } + SEXP before = CAR(token); + SEXP after = CDR(token); + SETCDR(before, after); + if (after != R_NilValue) { + SETCAR(after, before); + } +} +} + // only used for debugging SEXP get_rcpp_cache() { if (! Rcpp_cache_know) { diff --git a/src/rcpp_init.cpp b/src/rcpp_init.cpp index 4a6e00ccc..f67b97a89 100644 --- a/src/rcpp_init.cpp +++ b/src/rcpp_init.cpp @@ -1,8 +1,7 @@ -// -*- mode: C++; c-indent-level: 4; c-basic-offset: 4; indent-tabs-mode: nil; -*- -// + // Rcpp_init.cpp : Rcpp R/C++ interface class library -- Initialize and register // -// Copyright (C) 2010 - 2017 John Chambers, Dirk Eddelbuettel and Romain Francois +// Copyright (C) 2010 - 2020 John Chambers, Dirk Eddelbuettel and Romain Francois // // This file is part of Rcpp. // @@ -121,22 +120,27 @@ void registerFunctions(){ RCPP_REGISTER(error_occured) RCPP_REGISTER(rcpp_get_current_error) // RCPP_REGISTER(print) + RCPP_REGISTER(Rcpp_precious_init) + RCPP_REGISTER(Rcpp_precious_teardown) + RCPP_REGISTER(Rcpp_precious_preserve) + RCPP_REGISTER(Rcpp_precious_remove) #undef RCPP_REGISTER } - -extern "C" void R_unload_Rcpp(DllInfo *) { // #nocov start - // Release resources -} // #nocov end +extern "C" void R_unload_Rcpp(DllInfo *) { // #nocov start + Rcpp::Rcpp_precious_teardown(); // release resource +} // #nocov end extern "C" void R_init_Rcpp(DllInfo* dllinfo) { setCurrentScope(0); - registerFunctions(); // call wrapper to register export symbols + registerFunctions(); // call wrapper to register export symbols + + R_useDynamicSymbols(dllinfo, FALSE); // set up symbol symbol lookup (cf R 3.4.0) - R_useDynamicSymbols(dllinfo, FALSE); // set up symbol symbol lookup (cf R 3.4.0) + init_Rcpp_cache(); // init the cache - init_Rcpp_cache(); // init the cache + Rcpp::Rcpp_precious_init(); - init_Rcpp_routines(dllinfo); // init routines + init_Rcpp_routines(dllinfo); // init routines }