mirror of
https://github.com/janet-lang/janet
synced 2024-11-28 19:19:53 +00:00
Add janet_abstract_begin and janet_abstract_end
This will allow some one constructing an abstract to only make it visible to the garbage collector after it is in a valid state. If code in the constructing cfunction panics before janet_abstract_end is called, the GC will not try to mark the incomplete abstract type. This is often not needed through careful programming, but should work well.
This commit is contained in:
parent
4b4fe80404
commit
522545287e
@ -26,10 +26,19 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Create new userdata */
|
/* Create new userdata */
|
||||||
void *janet_abstract(const JanetAbstractType *atype, size_t size) {
|
void *janet_abstract_begin(const JanetAbstractType *atype, size_t size) {
|
||||||
JanetAbstractHead *header = janet_gcalloc(JANET_MEMORY_ABSTRACT,
|
JanetAbstractHead *header = janet_gcalloc(JANET_MEMORY_NONE,
|
||||||
sizeof(JanetAbstractHead) + size);
|
sizeof(JanetAbstractHead) + size);
|
||||||
header->size = size;
|
header->size = size;
|
||||||
header->type = atype;
|
header->type = atype;
|
||||||
return (void *) & (header->data);
|
return (void *) & (header->data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *janet_abstract_end(void *x) {
|
||||||
|
janet_gc_settype((void *)(janet_gc_header(x)), JANET_MEMORY_ABSTRACT);
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
void *janet_abstract(const JanetAbstractType *atype, size_t size) {
|
||||||
|
return janet_abstract_end(janet_abstract_begin(atype, size));
|
||||||
|
}
|
||||||
|
@ -990,6 +990,11 @@ static void peg_unmarshal(void *p, JanetMarshalContext *ctx) {
|
|||||||
peg->bytecode = NULL;
|
peg->bytecode = NULL;
|
||||||
peg->constants = NULL;
|
peg->constants = NULL;
|
||||||
|
|
||||||
|
/* Ensure not too large */
|
||||||
|
if (constants_start + sizeof(Janet) * peg->num_constants > janet_abstract_size(p)) {
|
||||||
|
janet_panic("size mismatch");
|
||||||
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < peg->bytecode_len; i++)
|
for (size_t i = 0; i < peg->bytecode_len; i++)
|
||||||
bytecode[i] = (uint32_t) janet_unmarshal_int(ctx);
|
bytecode[i] = (uint32_t) janet_unmarshal_int(ctx);
|
||||||
for (uint32_t j = 0; j < peg->num_constants; j++)
|
for (uint32_t j = 0; j < peg->num_constants; j++)
|
||||||
|
@ -1219,7 +1219,9 @@ JANET_API const JanetKV *janet_dictionary_next(const JanetKV *kvs, int32_t cap,
|
|||||||
#define janet_abstract_head(u) ((JanetAbstractHead *)((char *)u - offsetof(JanetAbstractHead, data)))
|
#define janet_abstract_head(u) ((JanetAbstractHead *)((char *)u - offsetof(JanetAbstractHead, data)))
|
||||||
#define janet_abstract_type(u) (janet_abstract_head(u)->type)
|
#define janet_abstract_type(u) (janet_abstract_head(u)->type)
|
||||||
#define janet_abstract_size(u) (janet_abstract_head(u)->size)
|
#define janet_abstract_size(u) (janet_abstract_head(u)->size)
|
||||||
JANET_API void *janet_abstract(const JanetAbstractType *type, size_t size);
|
JANET_API void *janet_abstract_begin(const JanetAbstractType *type, size_t size);
|
||||||
|
JANET_API void *janet_abstract_end(void *);
|
||||||
|
JANET_API void *janet_abstract(const JanetAbstractType *type, size_t size); /* begin and end in one call */
|
||||||
|
|
||||||
/* Native */
|
/* Native */
|
||||||
typedef void (*JanetModule)(JanetTable *);
|
typedef void (*JanetModule)(JanetTable *);
|
||||||
|
Loading…
Reference in New Issue
Block a user