summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKaz Kylheku <kaz@kylheku.com>2017-05-17 06:14:03 -0700
committerKaz Kylheku <kaz@kylheku.com>2017-05-17 06:14:03 -0700
commit3508e350cd21400171a204e8aec02ef41acbbde9 (patch)
tree2eff35aaa718f351096834d0f64aeb2897d73a14
parentb79f4f5a0b10d42a1904fb4d0a47b3c6076724be (diff)
downloadtxr-3508e350cd21400171a204e8aec02ef41acbbde9.tar.gz
txr-3508e350cd21400171a204e8aec02ef41acbbde9.tar.bz2
txr-3508e350cd21400171a204e8aec02ef41acbbde9.zip
ffi: carrays able to reference objects.
The idea here is that carrays can have a pointer to some area that is owned by another object. So that the area doesn't disappear when the other object becomes garbage, a carray which does this maintains a pointer to that other object. * ffi.c (ffi_carray_get): Pass new parameter to make_carray. (struct carray): New member, ref. (carray_mark_op): Mark new ref member. (make_carray): New parameter: the object which is stored in the structure as ref. (carray_dup): Null out the ref member. When a carray is duplicated, it owns its own buffer, and henceforth mustn't prevent the original object from being reclaimed. (carray_own): Don't allow a carray to claim ownership of the pointer if it references another object; we have no protocol to inform that other object. * ffi.h (make_carray): Declaration updated.
-rw-r--r--ffi.c17
-rw-r--r--ffi.h2
2 files changed, 14 insertions, 5 deletions
diff --git a/ffi.c b/ffi.c
index 31fee2eb..b2631941 100644
--- a/ffi.c
+++ b/ffi.c
@@ -1281,7 +1281,7 @@ static val ffi_varray_in(struct txr_ffi_type *tft, int copy, mem_t *src,
static val ffi_carray_get(struct txr_ffi_type *tft, mem_t *src, val self)
{
mem_t *p = *coerce(mem_t **, src);
- return make_carray(tft->mtypes, p, -1);
+ return make_carray(tft->mtypes, p, -1, nil);
}
static void ffi_carray_put(struct txr_ffi_type *tft, val carray, mem_t *dst,
@@ -2251,6 +2251,7 @@ struct carray {
struct txr_ffi_type *eltft;
mem_t *data;
cnum nelem;
+ val ref;
};
static struct carray *carray_struct(val carray)
@@ -2277,6 +2278,7 @@ static void carray_mark_op(val obj)
{
struct carray *scry = carray_struct(obj);
gc_mark(scry->eltype);
+ gc_mark(scry->ref);
}
static void carray_destroy_op(val obj)
@@ -2301,7 +2303,7 @@ static struct cobj_ops carray_owned_ops =
carray_mark_op,
cobj_eq_hash_op);
-val make_carray(val type, mem_t *data, cnum nelem)
+val make_carray(val type, mem_t *data, cnum nelem, val ref)
{
struct carray *scry = coerce(struct carray *, chk_malloc(sizeof *scry));
val obj;
@@ -2309,8 +2311,10 @@ val make_carray(val type, mem_t *data, cnum nelem)
scry->eltft = ffi_type_struct_checked(type);
scry->data = data;
scry->nelem = nelem;
+ scry->ref = nil;
obj = cobj(coerce(mem_t *, scry), carray_s, &carray_borrowed_ops);
scry->eltype = type;
+ scry->ref = ref;
return obj;
}
@@ -2356,13 +2360,18 @@ val carray_dup(val carray)
carray->co.ops = &carray_owned_ops;
scry->data = dup;
+ scry->ref = nil;
return t;
}
}
val carray_own(val carray)
{
- (void) carray_struct_checked(carray);
+ val self = lit("carray-own");
+ struct carray *scry = carray_struct_checked(carray);
+ if (scry->ref)
+ uw_throwf(error_s, lit("~a: cannot own buffer belonging to ~s"),
+ self, scry->ref, nao);
carray->co.ops = &carray_owned_ops;
return nil;
}
@@ -2430,7 +2439,7 @@ val carray_blank(val nelem, val type)
uw_throwf(error_s, lit("~a: negative array size"), self, nao);
} else {
mem_t *data = chk_calloc(nel, tft->size);
- val carray = make_carray(type, data, nel);
+ val carray = make_carray(type, data, nel, nil);
carray->co.ops = &carray_owned_ops;
return carray;
}
diff --git a/ffi.h b/ffi.h
index 0d82f29d..e9b188f2 100644
--- a/ffi.h
+++ b/ffi.h
@@ -63,7 +63,7 @@ val ffi_put(val obj, val type);
val ffi_in(val srcbuf, val obj, val type, val copy_p);
val ffi_get(val srcbuf, val type);
val ffi_out(val dstbuf, val obj, val type, val copy_p);
-val make_carray(val type, mem_t *data, cnum nelem);
+val make_carray(val type, mem_t *data, cnum nelem, val ref);
val carray_set_length(val carray, val nelem);
val carray_dup(val carray);
val carray_own(val carray);