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