summaryrefslogtreecommitdiff
path: root/libguile/guardians.c
diff options
context:
space:
mode:
authorJim Blandy <jimb@red-bean.com>1999-07-19 18:45:57 +0000
committerJim Blandy <jimb@red-bean.com>1999-07-19 18:45:57 +0000
commit55b7e0bd829bf604387aae1898c9b7e1e17d4ea8 (patch)
tree8c69e36c549ca624d1d71c18a202d114e504249f /libguile/guardians.c
parent6d8500ad76b5bac0e9fb6d7796ed7eaf052e53e0 (diff)
downloadguile-55b7e0bd829bf604387aae1898c9b7e1e17d4ea8.tar.gz
* guardians.c (scm_guardian_zombify): Don't set marks manually ---
use the macros. (Thanks to Michael Livshin.)
Diffstat (limited to 'libguile/guardians.c')
-rw-r--r--libguile/guardians.c45
1 files changed, 33 insertions, 12 deletions
diff --git a/libguile/guardians.c b/libguile/guardians.c
index d9cfc129b..3dd28a27c 100644
--- a/libguile/guardians.c
+++ b/libguile/guardians.c
@@ -176,12 +176,17 @@ void
scm_guardian_zombify ()
{
guardian_t *g;
+
+ /* Note that new guardians may be stuck on the end of the live
+ guardian list as we run this loop. As we move unmarked objects
+ to the zombie list and mark them, we may find some guarded
+ guardians. The guardian mark function will stick them on the end
+ of this list, so they'll be processed properly. */
for (g = first_live_guardian; g; g = g->next)
{
/* Loop through the live list and
1. move unmarked objects to the zombies tconc
- 2. mark the live tconc.
- */
+ 2. mark the live tconc. */
SCM tconc_tail = g->live.tail;
SCM prev_pair = SCM_BOOL_F;
SCM pair = g->live.head;
@@ -189,6 +194,21 @@ scm_guardian_zombify ()
{
SCM next_pair = SCM_CDR (pair);
+ /* Since next_pair is never assigned to, and since pair is
+ always set to next_pair at the end of the loop, we know
+ that this loop always reaches every pair in the tconc
+ once, except the tail.
+
+ At each iteration, we either throw the pair out of the
+ live list, or we mark it. And when we edit a pair's CDR,
+ we make sure to preserve its mark bit. So when this loop
+ terminates, all pairs left in the live tconc (except the
+ tail) have been marked.
+
+ Whenever we throw out a pair, we always relink the tconc,
+ so the tconc list structure is valid at the end of every
+ iteration. */
+
if (SCM_NMARKEDP (SCM_CAR (pair)))
{
/* got you, zombie! */
@@ -197,28 +217,29 @@ scm_guardian_zombify ()
if (SCM_FALSEP (prev_pair))
g->live.head = next_pair;
else
- /* mark previous pair */
- SCM_SETCDR (prev_pair, next_pair | 1);
+ {
+ SCM_SETCDR (prev_pair, next_pair);
+ /* Don't lose the mark bit! */
+ SCM_SETGCMARK (prev_pair);
+ }
/* to the zombie list! */
TCONC_IN (g->zombies, SCM_CAR (pair), pair);
}
else
{
- if (SCM_NFALSEP (prev_pair))
- /* mark previous pair */
- SCM_SETCDR (prev_pair, pair | 1);
+ SCM_SETGCMARK (pair);
prev_pair = pair;
}
pair = next_pair;
}
- if (SCM_NFALSEP (prev_pair))
- /* mark previous pair */
- SCM_SETCDR (prev_pair, pair | 1);
- /* mark live list tail */
- SCM_SETOR_CDR (tconc_tail, 1);
+ /* Mark the tconc's tail cell. All the other pairs in the tconc
+ are already marked. */
+ SCM_SETGCMARK (tconc_tail);
+
+ /* Bring the zombies back from the dead. */
scm_gc_mark (g->zombies.head);
}
}