83 lines
1.7 KiB
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;
|
|
}
|