1
0
mirror of https://github.com/janet-lang/janet synced 2024-06-16 10:19:55 +00:00

Have separate encode and decode dicts for threads

This is more correct and mirrors the way marshal -> unmarshal works.
This commit is contained in:
Calvin Rose 2019-12-01 21:53:39 -06:00
parent 5b1e59b535
commit 212479188a
4 changed files with 46 additions and 24 deletions

View File

@ -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)

View File

@ -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

View File

@ -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.")
},

View File

@ -957,7 +957,8 @@ struct JanetThreadShared {
};
struct JanetThread {
JanetThreadShared *shared;
JanetTable *dict;
JanetTable *encode;
JanetTable *decode;
enum {
JANET_THREAD_SELF,
JANET_THREAD_OTHER