#include "threads.h" #include "object.h" #include "pebblisp.h" #include #include #include struct Promise { int done; int refs; struct Environment* env; Object object; pthread_t thread; }; Object clonePromise(Object src) { src.promise->refs += 1; return src; } int isDone(struct Promise* promise) { return promise->done; } int isPromise(Object src) { return src.type == TYPE_PROMISE; } void cleanPromise(struct Promise* promise) { promise->refs -= 1; if (promise->refs == 0) { deleteEnv(promise->env); free(promise); } } Object await(Object* params, int length, struct Environment* env) { checkTypes(await) struct Promise* promise = params[0].promise; if (!promise->done) { // TODO: Does `done` need a mutex or other lock? pthread_join(promise->thread, NULL); } return cloneObject(promise->object); } void* doAsync(void* args) { struct Promise* promise = args; Object cloned = cloneObject(promise->object); Object first_eval = eval(&cloned, promise->env); Object e = funcyEval(&first_eval, NULL, 0, promise->env); promise->object = e; promise->done = 1; cleanPromise(promise); cleanObject(&cloned); return NULL; } Object async(Object* params, int length, struct Environment* env) { Object promise = newObject(TYPE_PROMISE); promise.promise = malloc(sizeof(struct Promise)); *promise.promise = (struct Promise) { .refs = 2, .done = 0, .env = env, .object = cloneObject(params[0]), }; pthread_create(&promise.promise->thread, NULL, doAsync, promise.promise); return promise; }