diff options
author | Tavian Barnes <tavianator@gmail.com> | 2009-06-22 21:56:19 +0000 |
---|---|---|
committer | Tavian Barnes <tavianator@gmail.com> | 2009-06-22 21:56:19 +0000 |
commit | efe600537740bb572f4a062ab6b9df12623e0c24 (patch) | |
tree | 0f7903c7a53fb068f87dc1a62d676ba00eb7f65e /libdimension/progress.c | |
parent | 9a72562eca9eb76e11439fb892a7b41bfc2c0a3e (diff) | |
download | dimension-efe600537740bb572f4a062ab6b9df12623e0c24.tar.xz |
Finish asynchronous PNG interface, and test it in png test.
Diffstat (limited to 'libdimension/progress.c')
-rw-r--r-- | libdimension/progress.c | 84 |
1 files changed, 75 insertions, 9 deletions
diff --git a/libdimension/progress.c b/libdimension/progress.c index e072f5d..aa6891c 100644 --- a/libdimension/progress.c +++ b/libdimension/progress.c @@ -25,9 +25,19 @@ dmnsn_progress * dmnsn_new_progress() { + dmnsn_progress_element element = { .progress = 0, .total = 1 }; dmnsn_progress *progress = malloc(sizeof(dmnsn_progress)); if (progress) { progress->elements = dmnsn_new_array(sizeof(dmnsn_progress_element)); + dmnsn_array_push(progress->elements, &element); + + if (pthread_cond_init(&progress->cond, NULL) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Couldn't initialize condition variable."); + } + if (pthread_mutex_init(&progress->mutex, NULL) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't initialize mutex."); + } } return progress; } @@ -36,6 +46,13 @@ void dmnsn_delete_progress(dmnsn_progress *progress) { if (progress) { + if (pthread_mutex_destroy(&progress->mutex) != 0) { + dmnsn_error(DMNSN_SEVERITY_LOW, "Leaking mutex."); + } + if (pthread_cond_destroy(&progress->cond) != 0) { + dmnsn_error(DMNSN_SEVERITY_LOW, "Leaking condition variable."); + } + dmnsn_delete_array(progress->elements); free(progress); } @@ -47,6 +64,10 @@ int dmnsn_finish_progress(dmnsn_progress *progress) int retval = 1; if (progress) { + if (pthread_cond_broadcast(&progress->cond) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't signal condition variable."); + } + if (pthread_join(progress->thread, &ptr) != 0) { /* Medium severity because an unjoined thread likely means that the thread is incomplete or invalid */ @@ -62,7 +83,7 @@ int dmnsn_finish_progress(dmnsn_progress *progress) } double -dmnsn_get_progress(const dmnsn_progress* progress) +dmnsn_get_progress(const dmnsn_progress *progress) { dmnsn_progress_element *element; double prog = 0.0; @@ -81,23 +102,68 @@ dmnsn_get_progress(const dmnsn_progress* progress) } void -dmnsn_new_progress_element(dmnsn_progress* progress, unsigned int total) +dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total) { dmnsn_progress_element element = { .progress = 0, .total = total }; dmnsn_array_push(progress->elements, &element); } void -dmnsn_increment_progress(dmnsn_progress* progress) +dmnsn_increment_progress(dmnsn_progress *progress) { dmnsn_progress_element *element; dmnsn_array_wrlock(progress->elements); - element = dmnsn_array_at(progress->elements, progress->elements->length - 1); - ++element->progress; - if (element->progress >= element->total) { - dmnsn_array_resize_unlocked(progress->elements, - progress->elements->length - 1); - } + element = dmnsn_array_at(progress->elements, progress->elements->length - 1); + ++element->progress; + + while (element->progress >= element->total + && progress->elements->length > 1) { + dmnsn_array_resize_unlocked(progress->elements, + progress->elements->length - 1); + element = dmnsn_array_at(progress->elements, progress->elements->length - 1); + ++element->progress; + } + + if (pthread_cond_broadcast(&progress->cond) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't signal condition variable."); + } dmnsn_array_unlock(progress->elements); } + +/* Immediately set to 100% completion */ +void +dmnsn_progress_done(dmnsn_progress *progress) +{ + dmnsn_progress_element *element; + + dmnsn_array_wrlock(progress->elements); + dmnsn_array_resize_unlocked(progress->elements, 1); + element = dmnsn_array_at(progress->elements, progress->elements->length - 1); + element->progress = element->total; + + if (pthread_cond_broadcast(&progress->cond) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't signal condition variable."); + } + dmnsn_array_unlock(progress->elements); +} + +/* Wait until dmnsn_get_progress(progress) >= prog */ +void +dmnsn_wait_progress(dmnsn_progress *progress, double prog) +{ + if (pthread_mutex_lock(&progress->mutex) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't lock condition mutex."); + } + + while (dmnsn_get_progress(progress) < prog) { + if (pthread_cond_wait(&progress->cond, &progress->mutex) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, + "Couldn't wait on condition variable."); + } + } + + if (pthread_mutex_unlock(&progress->mutex) != 0) { + dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't unlock condition mutex."); + } +} |