From 212479188a483505f2d5e4497a7d01d14a827af9 Mon Sep 17 00:00:00 2001 From: Calvin Rose Date: Sun, 1 Dec 2019 21:53:39 -0600 Subject: [PATCH] Have separate encode and decode dicts for threads This is more correct and mirrors the way marshal -> unmarshal works. --- examples/threads.janet | 2 +- src/boot/boot.janet | 13 ++++++++++- src/core/thread.c | 52 +++++++++++++++++++++++++----------------- src/include/janet.h | 3 ++- 4 files changed, 46 insertions(+), 24 deletions(-) diff --git a/examples/threads.janet b/examples/threads.janet index cbfc2649..9e379d9b 100644 --- a/examples/threads.janet +++ b/examples/threads.janet @@ -8,7 +8,7 @@ (defn make-worker [name] - (-> (thread/new make-image-dict) (thread/send worker-main) (thread/send name))) + (-> (thread/new) (thread/send worker-main) (thread/send name))) (def bob (make-worker "bob")) (os/sleep 0.5) diff --git a/src/boot/boot.janet b/src/boot/boot.janet index b09fbee0..fa4e83d1 100644 --- a/src/boot/boot.janet +++ b/src/boot/boot.janet @@ -1851,7 +1851,7 @@ (def load-image-dict "A table used in combination with unmarshal to unmarshal byte sequences created - by make-image, such that (load-image bytes) is the same as (unmarshal bytes load-images-dict)." + by make-image, such that (load-image bytes) is the same as (unmarshal bytes load-image-dict)." @{}) (defn make-image @@ -2068,6 +2068,17 @@ [& modules] ~(do ,;(map (fn [x] ~(,import* ,(string x) :prefix "")) modules))) +### +### +### Thread Extras +### +### + +(defn thread/new + "Create a new thread. Same as (thread/new-ext make-image-dict load-image-dict)." + [] + (thread/new-ext make-image-dict load-image-dict)) + ### ### ### REPL diff --git a/src/core/thread.c b/src/core/thread.c index 50bf90a7..136650f9 100644 --- a/src/core/thread.c +++ b/src/core/thread.c @@ -170,8 +170,11 @@ static int thread_gc(void *p, size_t size) { static int thread_mark(void *p, size_t size) { JanetThread *thread = (JanetThread *)p; (void) size; - if (NULL != thread->dict) { - janet_mark(janet_wrap_table(thread->dict)); + if (NULL != thread->encode) { + janet_mark(janet_wrap_table(thread->encode)); + } + if (NULL != thread->decode) { + janet_mark(janet_wrap_table(thread->decode)); } return 0; } @@ -187,11 +190,12 @@ static JanetAbstractType Thread_AT = { NULL }; -static JanetThread *janet_make_thread(JanetThreadShared *shared, JanetTable *dict, int who) { +static JanetThread *janet_make_thread(JanetThreadShared *shared, JanetTable *encode, JanetTable *decode, int who) { JanetThread *thread = janet_abstract(&Thread_AT, sizeof(JanetThread)); thread->shared = shared; thread->kind = who; - thread->dict = dict; + thread->encode = encode; + thread->decode = decode; return thread; } @@ -207,16 +211,26 @@ static int thread_worker(JanetThreadShared *shared) { /* Init VM */ janet_init(); - /* Get dictionary */ - JanetTable *dict = janet_core_dictionary(NULL); + /* Get dictionaries */ + JanetTable *decode = janet_core_dictionary(NULL); + JanetTable *encode = janet_table(decode->count); + for (int32_t i = 0; i < decode->capacity; i++) { + JanetKV *kv = decode->data + i; + if (!janet_checktype(kv->key, JANET_NIL)) { + janet_table_put(encode, kv->value, kv->key); + } + } + janet_gcroot(janet_wrap_table(encode)); /* Create self thread */ - JanetThread *thread = janet_make_thread(shared, dict, JANET_THREAD_SELF); + JanetThread *thread = janet_make_thread(shared, encode, decode, JANET_THREAD_SELF); + thread->encode = encode; + thread->decode = decode; Janet threadv = janet_wrap_abstract(thread); /* Unmarshal the function */ Janet funcv; - int status = janet_channel_receive(&shared->child, &funcv, dict); + int status = janet_channel_receive(&shared->child, &funcv, decode); if (status) goto error; if (!janet_checktype(funcv, JANET_FUNCTION)) goto error; JanetFunction *func = janet_unwrap_function(funcv); @@ -261,16 +275,12 @@ static void janet_thread_start_child(JanetThread *thread) { * Cfuns */ -static Janet cfun_thread_new(int32_t argc, Janet *argv) { - janet_arity(argc, 0, 1); - JanetTable *dict = NULL; - if (argc == 0 || janet_checktype(argv[0], JANET_NIL)) { - dict = janet_core_dictionary(NULL); - } else { - dict = janet_gettable(argv, 0); - } +static Janet cfun_thread_new_ext(int32_t argc, Janet *argv) { + janet_fixarity(argc, 2); + JanetTable *encode = janet_gettable(argv, 0); + JanetTable *decode = janet_gettable(argv, 1); JanetThreadShared *shared = janet_shared_create(0); - JanetThread *thread = janet_make_thread(shared, dict, JANET_THREAD_OTHER); + JanetThread *thread = janet_make_thread(shared, encode, decode, JANET_THREAD_OTHER); janet_thread_start_child(thread); return janet_wrap_abstract(thread); } @@ -282,7 +292,7 @@ static Janet cfun_thread_send(int32_t argc, Janet *argv) { if (NULL == shared) janet_panic("channel has closed"); int status = janet_channel_send(thread->kind == JANET_THREAD_SELF ? &shared->parent : &shared->child, argv[1], - thread->dict); + thread->encode); if (status) { janet_panicf("failed to send message %v", argv[1]); } @@ -297,7 +307,7 @@ static Janet cfun_thread_receive(int32_t argc, Janet *argv) { Janet out = janet_wrap_nil(); int status = janet_channel_receive(thread->kind == JANET_THREAD_SELF ? &shared->child : &shared->parent, &out, - thread->dict); + thread->decode); if (status) { janet_panic("failed to receive message"); } @@ -306,8 +316,8 @@ static Janet cfun_thread_receive(int32_t argc, Janet *argv) { static const JanetReg threadlib_cfuns[] = { { - "thread/new", cfun_thread_new, - JDOC("(thread/new &opt dict)\n\n" + "thread/new-ext", cfun_thread_new_ext, + JDOC("(thread/new-ext encode-book decode-book)\n\n" "Start a new thread. The thread will wait for a message containing the function used to start the thread, which should be subsequently " "sent over after thread creation.") }, diff --git a/src/include/janet.h b/src/include/janet.h index c2facb08..53cb13df 100644 --- a/src/include/janet.h +++ b/src/include/janet.h @@ -957,7 +957,8 @@ struct JanetThreadShared { }; struct JanetThread { JanetThreadShared *shared; - JanetTable *dict; + JanetTable *encode; + JanetTable *decode; enum { JANET_THREAD_SELF, JANET_THREAD_OTHER