-
Notifications
You must be signed in to change notification settings - Fork 7
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CRAN issues #120
Comments
Looks like the second aspect can be fixed too similar to what I found here (gotta love github search with 'cran' ...) (But I seem to have a Heisenbug effect under tests. Running |
This is the function called by SEXP asS4(SEXP s, Rboolean flag, int complete)
{
if(flag == IS_S4_OBJECT(s))
return s;
PROTECT(s);
if(MAYBE_SHARED(s)) {
s = shallow_duplicate(s);
UNPROTECT(1);
PROTECT(s);
}
if(flag) SET_S4_OBJECT(s);
else {
if(complete) {
SEXP value;
/* TENTATIVE: how much does this change? */
if((value = R_getS4DataSlot(s, ANYSXP))
!= R_NilValue && !IS_S4_OBJECT(value)) {
UNPROTECT(1);
return value;
}
/* else no plausible S3 object*/
else if(complete == 1) /* ordinary case (2, for conditional) */
error(_("object of class \"%s\" does not correspond to a valid S3 object"),
CHAR(STRING_ELT(R_data_class(s, FALSE), 0)));
else {
UNPROTECT(1);
return s; /* unchanged */
}
}
UNSET_S4_OBJECT(s);
}
UNPROTECT(1);
return s;
} Things work for me when changing: SET_S4_OBJECT(res); to: res = Rf_asS4(res, TRUE, FALSE); But not when there is no assignment to |
By "assignment" you refer to the subsequent |
No, I meant: res = Rf_asS4(res, TRUE, FALSE); instead of: Rf_asS4(res, TRUE, FALSE); The latter works only if a shallow duplicate is not made. Otherwise the S4 bit gets set on the copy and is not assigned to |
That is ... in a way even more puzzling. Maybe we can also step back and see if we can shimmy improvements into Rcpp::S4 which currently is fairly bare (but exists, mostly to get conveniently at a slot). |
All we want to do here is set the S4 bit on a newly created object; #define SET_S4_OBJECT(x) (((x)->sxpinfo.gp) |= S4_OBJECT_MASK) We are in full control of the object, so there should be no cases where the object is shared and no need for a duplicate (even shallow!). Looks like we'd be mainly just copying attributes and we don't have any, so it might all be OK in the end if we just replace with |
Yep. I got as far. Sadly the header info is hidden away. The assignment trick is already pretty good. |
So the reason Rcpp::NumericVector nanoival_get_start_impl(const Rcpp::ComplexVector cv) {
Rcpp::NumericVector res(cv.size());
Rcpp::Rcout << "Ref count just after allocation: " << REFCNT(res) << std::endl;
for (R_xlen_t i=0; i<cv.size(); ++i) {
interval ival;
Rcomplex c = cv[i];
memcpy(&ival, reinterpret_cast<const char*>(&c), sizeof(c));
if (ival.isNA()) {
double d;
memcpy(&d, reinterpret_cast<const char*>(&NA_INTEGER64), sizeof(NA_INTEGER64));
res[i] = d;
}
else {
std::int64_t start = ival.s;
double d;
memcpy(&d, reinterpret_cast<const char*>(&start), sizeof(start));
res[i] = d;
}
}
Rcpp::Rcout << "Ref count after filling in the start vector: " << REFCNT(res) << std::endl;
res.names() = cv.names();
Rcpp::Rcout << "Ref count after assigning the names: " << REFCNT(res) << std::endl;
return assignS4("nanotime", res, "integer64");
} when executed prints:
I believe this is happening in Anyway, a bit lost at this point. I will need to investigate closer the reference counting that is occurring in the names void set(SEXP x) {
Shield<SEXP> safe_x(x);
/* check if we can use a fast version */
if( TYPEOF(x) == STRSXP && parent.size() == Rf_length(x) ){
Rf_namesgets(parent, x);
} else {
/* use the slower and more flexible version (callback to R) */
SEXP namesSym = Rf_install( "names<-" );
Shield<SEXP> call(Rf_lang3(namesSym, parent, x));
Shield<SEXP> new_vec(Rcpp_fast_eval(call, R_GlobalEnv));
parent.set__(new_vec);
}
} Does any of this ring a bell? I'm thinking we could call Thoughts? |
I don't think Rcpp itself sets or increments the reference counters -- that is all deep down in R itself business by Luke. Shield<> etc should only be nicer-to-use and simpler-because-RAII variants of PROTECT / UNPROTECT unless I miss something. So moving assignS4 up an instruction or two seems fine to me. Can you try it? |
Tried it and it works. That's probably the best solution. Will go ahead and commit this, do you want me to also fix the missing \ in the |
Awesome. I can take care of roxygen2, that has come up elsewhere and gotten fixed (incl. at work). |
Confirming this local state of affairs passes muster: modified inst/include/nanotime/utilities.hpp
@@ -48,8 +48,8 @@ namespace nanotime {
SEXP assignS4(const char* classname, Rcpp::Vector<R>& res) {
Rcpp::CharacterVector cl = Rcpp::CharacterVector::create(classname);
cl.attr("package") = "nanotime";
+ Rf_asS4(res, TRUE, FALSE);
res.attr("class") = cl;
- SET_S4_OBJECT(res);
return Rcpp::S4(res);
}
@@ -61,11 +61,37 @@ namespace nanotime {
Rcpp::CharacterVector cl = Rcpp::CharacterVector::create(classname);
cl.attr("package") = "nanotime";
res.attr("class") = cl;
+ res = Rf_asS4(res, TRUE, FALSE);
// use 'install' here as in R source code attrib.c: LLL
Rcpp::CharacterVector oc = Rcpp::CharacterVector::create(oldClass);
res.attr(".S3Class") = oc;
- SET_S4_OBJECT(res);
return Rcpp::S4(res); |
The name copying order also needs to be changed in |
No strong feelings. Separate issues (as #121 and #117 seem to be) may warrant separate PRs... I am getting quite used to squashing PRs (as we do at work, started it for Rcpp a while back too) which makes things nice and linear. Order doesn't matter. I can wrap up #121 and was about to suggest to ship to CRAN but we may to hit #117 over the head too. So maybe create a new branch for #117, or wait til #121 is in, or ... It all works. |
BTW I checked the change under r-devel and I don't think i had the |
OK, I'll fix #117 tonight in a different PR and like that we can submit to CRAN only once. Without the change in |
Ok, I will squash merge #121 then so you have clean slate to start from. Onwards, and forwards, and big big thanks for working through this one where I only managed half of it at best. |
If found the '\code{+}' issue (reported at CRAN). Might be easiest to remove the outer backticks around |
Naaa, I already fixed that issue weeks in this commit. Sorry for a) not making that clearer and b) not going via a PR so that you saw it. |
We apparently have two CRAN issues outside the long-fixed 'do not specify C++11 unless needed' we addressed ages ago.
One is just a typo. R-devel checks more carefully for 'isolated' pairs of
{}
we have onecode{+}
that wants to be\code{+}
. I will fix that in a second. (One aside is that we do something that upsetsroxygen2
on my machine. It errors with"S3 method {.arg {name}} needs @export or @exportS3method tag")
and dies.)The other is that of late Brian Ripley is chasing more uses of functions from 'internal' headers and our use of
SET_S4_OBJECT
is flagged, twice. The function is a simple one-liner so we could internalize, or we could replace the S4 creation with a call from C++ to R and call a propernew(...)
. Thoughts?The text was updated successfully, but these errors were encountered: