This is… nothing. I’m just re-inventing the wheel only to have slightly better understanding about what extendr does.
This framework uses tagged pointer to indicate the error. This requires some wrappers, but the advantage is that we don’t need to pass additional data and these bit operations should be cheap.
See extendr/extendr#278 for more discussion.
I implemented the doubly-linked list method, which cpp11 uses. Now I’m not sure if this fits extendr; probably its current implementation aims for parallel processing, so it needs a hashmap to prevent collisions. But, I think it’s not a good idea to use R’s C API concurrently anyway, so this should be probably enough.
cpp11 provides the read-only by default, and the writable version as an option.It seems a good idea to distinguish the external SEXPs and the “owned” SEXPs because we have control, when to protect and unprotect, only over the latter one.
Regarding the concurrency, I’m wondering if it would be simpler if extendr give up supporting embedded usages. Yes, extendr is not only about R packages. It also provides functionalities to embed R in Rust like this one. This is great, but, on the other hand, this means we have to care a lot of things. But, how careful we try to be, concurrency is a tough job.
A lot of tests have failed because of various problems related to
concurrency. Every time we encountered such a failure, we place
single_threaded()
here and there. But, could all of them really happen
inside an R package? If extendr gives up supporting embedded usages, can
our life be simpler a bit?
library(unextendr)
to_upper(c("a", NA, "A", "座布団一枚"))
#> [1] "A" NA "A" "座布団一枚"
times_two_int(c(1L, NA, 100L, 0L, -1L))
#> [1] 2 NA 200 0 -2
times_two_numeric(c(1.1, NA, 0.0, Inf, -Inf))
#> [1] 2.2 NA 0.0 Inf -Inf
flip_logical(c(TRUE, FALSE, NA))
#> [1] FALSE TRUE TRUE
- Support Attribute and names
- Support list
- Support ALTREP
- Use proc-macro
-
R_UnwindProtect()