@@ -315,16 +315,18 @@ static struct {
315
315
316
316
static SEXP list_ = get_preserve_list ();
317
317
318
- // Add a new cell that points to the previous end.
319
- SEXP cell = PROTECT (Rf_cons (list_, CDR (list_)));
318
+ // Get references to head, tail of the precious list.
319
+ SEXP head = list_;
320
+ SEXP tail = CDR (list_);
320
321
322
+ // Add a new cell that points to the current head + tail.
323
+ SEXP cell = PROTECT (Rf_cons (head, tail));
321
324
SET_TAG (cell, obj);
322
325
323
- SETCDR (list_, cell);
324
-
325
- if (CDR (cell) != R_NilValue) {
326
- SETCAR (CDR (cell), cell);
327
- }
326
+ // Update the head + tail to point at the newly-created cell,
327
+ // effectively inserting that cell between the current head + tail.
328
+ SETCDR (head, cell);
329
+ SETCAR (tail, cell);
328
330
329
331
UNPROTECT (2 );
330
332
@@ -352,29 +354,25 @@ static struct {
352
354
#endif
353
355
}
354
356
355
- void release (SEXP token ) {
356
- if (token == R_NilValue) {
357
+ void release (SEXP cell ) {
358
+ if (cell == R_NilValue) {
357
359
return ;
358
360
}
359
361
360
362
#ifdef CPP11_USE_PRESERVE_OBJECT
361
- R_ReleaseObject (token );
363
+ R_ReleaseObject (cell );
362
364
return ;
363
365
#endif
364
366
365
- SEXP before = CAR (token);
366
-
367
- SEXP after = CDR (token);
368
-
369
- if (before == R_NilValue && after == R_NilValue) {
370
- Rf_error (" should never happen" );
371
- }
372
-
373
- SETCDR (before, after);
367
+ // Get a reference to the cells before and after the token.
368
+ SEXP lhs = CAR (cell);
369
+ SEXP rhs = CDR (cell);
374
370
375
- if (after != R_NilValue) {
376
- SETCAR (after, before);
377
- }
371
+ // Remove the cell from the precious list -- effectively, we do this
372
+ // by updating the 'lhs' and 'rhs' references to point at each-other,
373
+ // effectively removing any references to the cell in the pairlist.
374
+ SETCDR (lhs, rhs);
375
+ SETCAR (rhs, lhs);
378
376
}
379
377
380
378
private:
@@ -414,18 +412,24 @@ static struct {
414
412
415
413
static SEXP get_preserve_list () {
416
414
static SEXP preserve_list = R_NilValue;
417
-
418
415
if (TYPEOF (preserve_list) != LISTSXP) {
419
416
preserve_list = get_preserve_xptr_addr ();
420
417
if (TYPEOF (preserve_list) != LISTSXP) {
421
- preserve_list = Rf_cons (R_NilValue, R_NilValue);
418
+ preserve_list = Rf_cons (R_NilValue, Rf_cons ( R_NilValue, R_NilValue) );
422
419
R_PreserveObject (preserve_list);
423
420
set_preserve_xptr (preserve_list);
424
421
}
422
+
423
+ // NOTE: Because older versions of cpp11 (<= 0.4.2) initialized the
424
+ // precious_list with a single cell, we might need to detect and update
425
+ // an existing empty precious list so that we have a second cell following.
426
+ if (CDR (preserve_list) == R_NilValue)
427
+ SETCDR (preserve_list, Rf_cons (R_NilValue, R_NilValue));
425
428
}
426
429
427
430
return preserve_list;
428
431
}
429
- } // namespace cpp11
430
- preserved;
432
+
433
+ } preserved;
434
+
431
435
} // namespace cpp11
0 commit comments