pebblisp/src/threads.c

83 lines
1.7 KiB
C

#include "threads.h"
#include "object.h"
#include "pebblisp.h"
#include <stdlib.h>
#include <pthread.h>
#include <unistd.h>
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]),
};
env->refs += 1;
pthread_create(&promise.promise->thread, NULL, doAsync, promise.promise);
return promise;
}