summaryrefslogtreecommitdiffhomepage
path: root/lib.c
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2022-08-12 00:22:26 +0200
committerJo-Philipp Wich <jo@mein.io>2022-08-12 01:23:27 +0200
commit85d7885e226ed79dc071e0cef73ccc918144a8f5 (patch)
tree0e56769cd7fbe473c18a656b1f63d256a7856547 /lib.c
parent47528f02e7376f1fbb205c5cf69d17d55619fcb1 (diff)
lib: implement gc()
Introduce a new stdlib function `gc()` which allows controlling the periodic garbage collector from ucode. Signed-off-by: Jo-Philipp Wich <jo@mein.io>
Diffstat (limited to 'lib.c')
-rw-r--r--lib.c44
1 files changed, 44 insertions, 0 deletions
diff --git a/lib.c b/lib.c
index 7a04cdd..1cbde6d 100644
--- a/lib.c
+++ b/lib.c
@@ -3519,6 +3519,49 @@ uc_hexdec(uc_vm_t *vm, size_t nargs)
return ucv_stringbuf_finish(buf);
}
+static uc_value_t *
+uc_gc(uc_vm_t *vm, size_t nargs)
+{
+ uc_value_t *operation = uc_fn_arg(0);
+ uc_value_t *argument = uc_fn_arg(1);
+ const char *op = NULL;
+ uc_weakref_t *ref;
+ int64_t n;
+
+ if (operation != NULL && ucv_type(operation) != UC_STRING)
+ return NULL;
+
+ op = ucv_string_get(operation);
+
+ if (!op || !strcmp(op, "collect")) {
+ ucv_gc(vm);
+
+ return ucv_boolean_new(true);
+ }
+ else if (!strcmp(op, "start")) {
+ n = argument ? ucv_int64_get(argument) : 0;
+
+ if (errno || n < 0 || n > 0xFFFF)
+ return NULL;
+
+ if (n == 0)
+ n = GC_DEFAULT_INTERVAL;
+
+ return ucv_boolean_new(uc_vm_gc_start(vm, n));
+ }
+ else if (!strcmp(op, "stop")) {
+ return ucv_boolean_new(uc_vm_gc_stop(vm));
+ }
+ else if (!strcmp(op, "count")) {
+ for (n = 0, ref = vm->values.next; ref != &vm->values; ref = ref->next)
+ n++;
+
+ return ucv_uint64_new(n);
+ }
+
+ return NULL;
+}
+
const uc_function_list_t uc_stdlib_functions[] = {
{ "chr", uc_chr },
@@ -3586,6 +3629,7 @@ const uc_function_list_t uc_stdlib_functions[] = {
{ "clock", uc_clock },
{ "hexdec", uc_hexdec },
{ "hexenc", uc_hexenc },
+ { "gc", uc_gc }
};