use weak map to control writer
This commit is contained in:
parent
efa15fd5ce
commit
5bd390aa79
|
@ -14,9 +14,9 @@ KHASH_DEFINE2(v, void *, int, 1, kh_ptr_hash_func, kh_ptr_hash_equal)
|
|||
struct writer_control {
|
||||
int mode;
|
||||
int op;
|
||||
khash_t(l) labels; /* object -> int */
|
||||
khash_t(v) visited; /* is object shared? (yes if >0) */
|
||||
int cnt;
|
||||
pic_value shared; /* is object shared? (yes if >0) */
|
||||
pic_value labels; /* object -> int */
|
||||
};
|
||||
|
||||
#define WRITE_MODE 1
|
||||
|
@ -27,25 +27,20 @@ struct writer_control {
|
|||
#define OP_WRITE_SIMPLE 3
|
||||
|
||||
static void
|
||||
writer_control_init(struct writer_control *p, int mode, int op)
|
||||
writer_control_init(pic_state *pic, struct writer_control *p, int mode, int op)
|
||||
{
|
||||
p->mode = mode;
|
||||
p->op = op;
|
||||
p->cnt = 0;
|
||||
kh_init(l, &p->labels);
|
||||
kh_init(v, &p->visited);
|
||||
}
|
||||
|
||||
static void
|
||||
writer_control_destroy(pic_state *pic, struct writer_control *p)
|
||||
{
|
||||
kh_destroy(l, &p->labels);
|
||||
kh_destroy(v, &p->visited);
|
||||
p->shared = pic_make_weak(pic);
|
||||
p->labels = pic_make_weak(pic);
|
||||
}
|
||||
|
||||
static void
|
||||
traverse(pic_state *pic, pic_value obj, struct writer_control *p)
|
||||
{
|
||||
pic_value shared = p->shared;
|
||||
|
||||
if (p->op == OP_WRITE_SIMPLE) {
|
||||
return;
|
||||
}
|
||||
|
@ -54,14 +49,10 @@ traverse(pic_state *pic, pic_value obj, struct writer_control *p)
|
|||
case PIC_TYPE_PAIR:
|
||||
case PIC_TYPE_VECTOR:
|
||||
case PIC_TYPE_DICT: {
|
||||
khash_t(v) *h = &p->visited;
|
||||
int it;
|
||||
int ret;
|
||||
|
||||
it = kh_put(v, h, pic_obj_ptr(obj), &ret);
|
||||
if (ret != 0) {
|
||||
if (! pic_weak_has(pic, shared, obj)) {
|
||||
/* first time */
|
||||
kh_val(h, it) = 0;
|
||||
pic_weak_set(pic, shared, obj, pic_int_value(pic, 0));
|
||||
|
||||
if (pic_pair_p(pic, obj)) {
|
||||
/* pair */
|
||||
|
@ -83,14 +74,13 @@ traverse(pic_state *pic, pic_value obj, struct writer_control *p)
|
|||
}
|
||||
|
||||
if (p->op == OP_WRITE) {
|
||||
it = kh_get(v, h, pic_obj_ptr(obj));
|
||||
if (kh_val(h, it) == 0) {
|
||||
kh_del(v, h, it);
|
||||
if (pic_int(pic, pic_weak_ref(pic, shared, obj)) == 0) {
|
||||
pic_weak_del(pic, shared, obj);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* second time */
|
||||
kh_val(h, it) = 1;
|
||||
pic_weak_set(pic, shared, obj, pic_int_value(pic, 1));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
@ -101,17 +91,15 @@ traverse(pic_state *pic, pic_value obj, struct writer_control *p)
|
|||
|
||||
static bool
|
||||
is_shared_object(pic_state *pic, pic_value obj, struct writer_control *p) {
|
||||
khash_t(v) *h = &p->visited;
|
||||
int it;
|
||||
pic_value shared = p->shared;
|
||||
|
||||
if (! pic_obj_p(pic, obj)) {
|
||||
return false;
|
||||
}
|
||||
it = kh_get(v, h, pic_obj_ptr(obj));
|
||||
if (it == kh_end(h)) {
|
||||
if (! pic_weak_has(pic, shared, obj)) {
|
||||
return false;
|
||||
}
|
||||
return kh_val(h, it) > 0;
|
||||
return pic_int(pic, pic_weak_ref(pic, shared, obj)) > 0;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -297,17 +285,18 @@ write_dict(pic_state *pic, pic_value dict, xFILE *file, struct writer_control *p
|
|||
static void
|
||||
write_core(pic_state *pic, pic_value obj, xFILE *file, struct writer_control *p)
|
||||
{
|
||||
khash_t(l) *lh = &p->labels;
|
||||
int it, ret;
|
||||
pic_value labels = p->labels;
|
||||
int i;
|
||||
|
||||
/* shared objects */
|
||||
if (is_shared_object(pic, obj, p)) {
|
||||
it = kh_put(l, lh, pic_obj_ptr(obj), &ret);
|
||||
if (ret == 0) { /* if exists */
|
||||
xfprintf(pic, file, "#%d#", kh_val(lh, it));
|
||||
if (pic_weak_has(pic, labels, obj)) {
|
||||
xfprintf(pic, file, "#%d#", pic_int(pic, pic_weak_ref(pic, labels, obj)));
|
||||
return;
|
||||
}
|
||||
xfprintf(pic, file, "#%d=", (kh_val(lh, it) = p->cnt++));
|
||||
i = p->cnt++;
|
||||
xfprintf(pic, file, "#%d=", i);
|
||||
pic_weak_set(pic, labels, obj, pic_int_value(pic, i));
|
||||
}
|
||||
|
||||
switch (pic_type(pic, obj)) {
|
||||
|
@ -363,7 +352,7 @@ write_core(pic_state *pic, pic_value obj, xFILE *file, struct writer_control *p)
|
|||
|
||||
if (p->op == OP_WRITE) {
|
||||
if (is_shared_object(pic, obj, p)) {
|
||||
kh_del(l, lh, kh_get(l, lh, pic_obj_ptr(obj)));
|
||||
pic_weak_del(pic, labels, obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -373,13 +362,11 @@ write(pic_state *pic, pic_value obj, xFILE *file, int mode, int op)
|
|||
{
|
||||
struct writer_control p;
|
||||
|
||||
writer_control_init(&p, mode, op);
|
||||
writer_control_init(pic, &p, mode, op);
|
||||
|
||||
traverse(pic, obj, &p);
|
||||
|
||||
write_core(pic, obj, file, &p);
|
||||
|
||||
writer_control_destroy(pic, &p);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue