Files

89 lines
2.4 KiB
C
Raw Permalink Normal View History

2015-06-28 11:18:05 -07:00
#include <assert.h>
#include <pthread.h>
#include <stdlib.h>
#include "promise.h"
struct promise {
promise_callback on_success;
promise_callback on_failure;
void *passthrough;
bool fulfilled;
pthread_mutex_t lock;
pthread_cond_t cond;
bool success;
void *result;
promise_cleanup cleanup;
2015-06-28 11:18:05 -07:00
};
promise *promise_create(promise_callback on_success, promise_callback on_failure, void *passthrough) {
2015-06-28 11:18:05 -07:00
promise *promise_obj = malloc(sizeof(*promise_obj));
promise_obj->on_success = on_success;
promise_obj->on_failure = on_failure;
promise_obj->passthrough = passthrough;
promise_obj->fulfilled = false;
assert(!pthread_mutex_init(&promise_obj->lock, NULL));
assert(!pthread_cond_init(&promise_obj->cond, NULL));
return promise_obj;
}
void promise_destroy(promise *promise_obj) {
2015-07-06 01:43:56 +00:00
assert(promise_obj->fulfilled);
2015-06-28 11:18:05 -07:00
assert(!pthread_mutex_destroy(&promise_obj->lock));
assert(!pthread_cond_destroy(&promise_obj->cond));
if (promise_obj->result && promise_obj->cleanup) {
promise_obj->cleanup(promise_obj->result);
}
2015-06-28 11:18:05 -07:00
free(promise_obj);
}
bool promise_wait(promise *promise_obj, void **result) {
2015-06-28 12:22:23 -07:00
assert(promise_obj);
2015-06-28 11:18:05 -07:00
assert(!pthread_mutex_lock(&promise_obj->lock));
while (!promise_obj->fulfilled) {
pthread_cond_wait(&promise_obj->cond, &promise_obj->lock);
}
assert(!pthread_mutex_unlock(&promise_obj->lock));
bool success = promise_obj->success;
if (result) {
*result = promise_obj->result;
}
return success;
}
void promise_complete(promise *promise_obj, void *result, promise_cleanup cleanup, bool success) {
2015-06-28 12:22:23 -07:00
if (!promise_obj) {
if (result && cleanup) {
cleanup(result);
}
2015-06-28 12:22:23 -07:00
return;
}
2015-06-28 11:18:05 -07:00
assert(!pthread_mutex_lock(&promise_obj->lock));
if (success && promise_obj->on_success) {
promise_obj->on_success(promise_obj->passthrough, result);
} else if (!success && promise_obj->on_failure) {
promise_obj->on_failure(promise_obj->passthrough, result);
}
promise_obj->result = result;
promise_obj->cleanup = cleanup;
promise_obj->success = success;
promise_obj->fulfilled = true;
assert(!pthread_cond_signal(&promise_obj->cond));
assert(!pthread_mutex_unlock(&promise_obj->lock));
2015-06-28 11:18:05 -07:00
}
void promise_succeed(promise *promise_obj, void *result, promise_cleanup cleanup) {
promise_complete(promise_obj, result, cleanup, true);
2015-06-28 11:18:05 -07:00
}
void promise_fail(promise *promise_obj, void *result, promise_cleanup cleanup) {
promise_complete(promise_obj, result, cleanup, false);
2015-06-28 11:18:05 -07:00
}