diff options
Diffstat (limited to 'src/pkg/runtime/mfinal.c')
-rw-r--r-- | src/pkg/runtime/mfinal.c | 60 |
1 files changed, 38 insertions, 22 deletions
diff --git a/src/pkg/runtime/mfinal.c b/src/pkg/runtime/mfinal.c index 817d98737..ae737e8da 100644 --- a/src/pkg/runtime/mfinal.c +++ b/src/pkg/runtime/mfinal.c @@ -18,17 +18,14 @@ typedef struct Fintab Fintab; struct Fintab { void **key; - struct { - void *fn; - int32 nret; - } *val; + Finalizer **val; int32 nkey; // number of non-nil entries in key int32 ndead; // number of dead (-1) entries in key int32 max; // size of key, val allocations }; static void -addfintab(Fintab *t, void *k, void *fn, int32 nret) +addfintab(Fintab *t, void *k, Finalizer *v) { int32 i, j; @@ -51,15 +48,14 @@ addfintab(Fintab *t, void *k, void *fn, int32 nret) ret: t->key[i] = k; - t->val[i].fn = fn; - t->val[i].nret = nret; + t->val[i] = v; } -static void* -lookfintab(Fintab *t, void *k, bool del, int32 *nret) +static Finalizer* +lookfintab(Fintab *t, void *k, bool del) { int32 i, j; - void *v; + Finalizer *v; if(t->max == 0) return nil; @@ -68,13 +64,10 @@ lookfintab(Fintab *t, void *k, bool del, int32 *nret) if(t->key[i] == nil) return nil; if(t->key[i] == k) { - v = t->val[i].fn; - if(nret) - *nret = t->val[i].nret; + v = t->val[i]; if(del) { t->key[i] = (void*)-1; - t->val[i].fn = nil; - t->val[i].nret = 0; + t->val[i] = nil; t->ndead++; } return v; @@ -98,6 +91,14 @@ addfinalizer(void *p, void (*f)(void*), int32 nret) int32 i; uint32 *ref; byte *base; + Finalizer *e; + + e = nil; + if(f != nil) { + e = mal(sizeof *e); + e->fn = f; + e->nret = nret; + } lock(&finlock); if(!mlookup(p, &base, nil, nil, &ref) || p != base) { @@ -106,7 +107,7 @@ addfinalizer(void *p, void (*f)(void*), int32 nret) } if(f == nil) { if(*ref & RefHasFinalizer) { - lookfintab(&fintab, p, 1, nil); + lookfintab(&fintab, p, 1); *ref &= ~RefHasFinalizer; } unlock(&finlock); @@ -141,26 +142,41 @@ addfinalizer(void *p, void (*f)(void*), int32 nret) k = fintab.key[i]; if(k != nil && k != (void*)-1) - addfintab(&newtab, k, fintab.val[i].fn, fintab.val[i].nret); + addfintab(&newtab, k, fintab.val[i]); } free(fintab.key); free(fintab.val); fintab = newtab; } - addfintab(&fintab, p, f, nret); + addfintab(&fintab, p, e); unlock(&finlock); } // get finalizer; if del, delete finalizer. // caller is responsible for updating RefHasFinalizer bit. -void* -getfinalizer(void *p, bool del, int32 *nret) +Finalizer* +getfinalizer(void *p, bool del) { - void *f; + Finalizer *f; lock(&finlock); - f = lookfintab(&fintab, p, del, nret); + f = lookfintab(&fintab, p, del); unlock(&finlock); return f; } + +void +walkfintab(void (*fn)(void*)) +{ + void **key; + void **ekey; + + lock(&finlock); + key = fintab.key; + ekey = key + fintab.max; + for(; key < ekey; key++) + if(*key != nil && *key != ((void*)-1)) + fn(*key); + unlock(&finlock); +} |