void WeakRef::markThru() { WeakRef::check(); WRList newlive; // Step 2-3 of algorithm. Mark the value and R finalizer if the // key is marked. { unsigned int marks_applied; do { GCNode::Marker marker; WRList::iterator lit = s_live->begin(); while (lit != s_live->end()) { WeakRef* wr = *lit++; RObject* key = wr->key(); if (key->isMarked()) { RObject* value = wr->value(); if (value) marker(value); FunctionBase* Rfinalizer = wr->m_Rfinalizer; if (Rfinalizer) marker(Rfinalizer); wr->transfer(s_live, &newlive); } } marks_applied = marker.marksApplied(); } while (marks_applied > 0); } // Step 4 of algorithm. Process references with unmarked keys. { GCNode::Marker marker; WRList::iterator lit = s_live->begin(); while (lit != s_live->end()) { WeakRef* wr = *lit++; FunctionBase* Rfinalizer = wr->m_Rfinalizer; if (Rfinalizer) marker(Rfinalizer); if (Rfinalizer || wr->m_Cfinalizer) { marker(wr); marker(wr->m_key); wr->m_ready_to_finalize = true; wr->transfer(s_live, s_f10n_pending); } else { wr->tombstone(); // Expose to reference-counting collection: wr->m_self = 0; } } } // Step 5 of algorithm. Mark all live references with reachable keys. { GCNode::Marker marker; s_live->splice(s_live->end(), newlive); for (WRList::iterator lit = s_live->begin(); lit != s_live->end(); ++lit) { WeakRef* wr = *lit; marker(wr); } } }
SEXP R_WeakRefValue(SEXP w) { if (w->sexptype() != WEAKREFSXP) Rf_error(_("not a weak reference")); WeakRef* wr = static_cast<WeakRef*>(w); SEXP v = wr->value(); if (v && NAMED(v) != 2) SET_NAMED(v, 2); return v; }