Luke Tierney <luke (AT) stat (DOT) uiowa.eduwrote:
This is not supported by the memory manager. Using SETLENGTH to
change the length would confuse the garbage collector should
probably remove SETLENGTH from the headers.
The memory manager does over-allocate small vectors by rounding up to
convenient sizes, and the real size could be computed, but this is not
true for large allocations correspond to malloc calls for the
requested size in any case the memory manager relies on LENGTH
giving the correct amount (maybe not heavily but this could change).
A GC does not move objects.
Using R level vectors for the purpose you describe is in any case
tricky since it is hard to reliably prevent copying. You are better
off using something like an external pointer into an R-allocated
object that is only accessible through the external pointer. Then you
can manage the filled length yourself.
since GC does not move objects, and large vectors are allocated
using a regular malloc, and malloc/free manages space independent of
the LENGTH information, it seems that SETLENGTH would be "safe" if it
was possible to guarantee for an interval of time that this particular
value would not be moved or released due to any user activity?
What if I create the full-length vector, make it visible using
defineVar(), then protect the vector by creating a reference with
R_MakeExternalPtr(), and R_P() this reference? Then
shouldn't the vector be left alone until I release the reference?
And I could then play with SETLENGTH() on that vector safely, so long
as I restore it before releasing the reference, and so long as I only
perform operations that modify the vector in-place?
i.e., should something like this work:
static SEXP ptr;
do_init()
{
SEXP s = PRTECT(allocVector(RAWSXP, 1000));
defineVar("mystuff", s, R_BaseEnv);
ptr = R_MakeExternalPtr(RAW(s), R_NilValue, s);
R_P(ptr);
SETLENGTH(s, 0);
UNPRTECT(1);
}
do_extend()
{
SEXP s = R_ExternalPtrProtected(ptr);
memcpy(RAW(s)+LENGTH(s), "xxxx", 4);
SETLENGTH(s, LENGTH(s)+4);
}
do_finish()
{
SEXP s = R_ExternalPtrProtected(ptr);
SETLENGTH(s, 1000);
R_R(ptr);
}
i.e., if the user tries to modify "mystuff", they'll end up with a
copy, but the value pointed to by ptr will hang around (no longer
accessible by the user) until do_finish() is called?
-- Dave
R-devel (AT) r-project (DOT) org mailing list