diff options
-rw-r--r-- | libdimension/dimension/progress.h | 9 | ||||
-rw-r--r-- | libdimension/progress.c | 88 |
2 files changed, 62 insertions, 35 deletions
diff --git a/libdimension/dimension/progress.h b/libdimension/dimension/progress.h index 194ae83..a865c8f 100644 --- a/libdimension/dimension/progress.h +++ b/libdimension/dimension/progress.h @@ -38,8 +38,8 @@ typedef struct { pthread_t thread; /* Condition variable for waiting for a particular amount of progress */ - pthread_cond_t cond; - pthread_mutex_t mutex; + pthread_cond_t *cond; + pthread_mutex_t *mutex; } dmnsn_progress; dmnsn_progress *dmnsn_new_progress(); @@ -49,12 +49,11 @@ void dmnsn_delete_progress(dmnsn_progress *progress); addition to deleting `progress' */ int dmnsn_finish_progress(dmnsn_progress *progress); -double dmnsn_get_progress(const dmnsn_progress* progress); +double dmnsn_get_progress(const dmnsn_progress *progress); +void dmnsn_wait_progress(const dmnsn_progress *progress, double prog); void dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total); void dmnsn_increment_progress(dmnsn_progress *progress); void dmnsn_progress_done(dmnsn_progress *progress); -void dmnsn_wait_progress(dmnsn_progress *progress, double prog); - #endif /* DIMENSION_PROGRESS_H */ diff --git a/libdimension/progress.c b/libdimension/progress.c index dc0339c..29469a6 100644 --- a/libdimension/progress.c +++ b/libdimension/progress.c @@ -32,12 +32,38 @@ dmnsn_new_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."); + progress->cond = malloc(sizeof(pthread_cond_t)); + if (!progress->cond) { + dmnsn_delete_array(progress->elements); + free(progress); + return NULL; + } + + progress->mutex = malloc(sizeof(pthread_mutex_t)); + if (!progress->mutex) { + free(progress->cond); + dmnsn_delete_array(progress->elements); + free(progress); + return NULL; + } + + if (pthread_cond_init(progress->cond, NULL) != 0) { + free(progress->mutex); + free(progress->cond); + dmnsn_delete_array(progress->elements); + free(progress); + return NULL; } - if (pthread_mutex_init(&progress->mutex, NULL) != 0) { - dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't initialize mutex."); + if (pthread_mutex_init(progress->mutex, NULL) != 0) { + if (pthread_cond_destroy(progress->cond) != 0) { + dmnsn_error(DMNSN_SEVERITY_LOW, + "Leaking condition variable in failed allocation."); + } + free(progress->mutex); + free(progress->cond); + dmnsn_delete_array(progress->elements); + free(progress); + return NULL; } } return progress; @@ -49,13 +75,15 @@ void dmnsn_delete_progress(dmnsn_progress *progress) { if (progress) { - if (pthread_mutex_destroy(&progress->mutex) != 0) { + if (pthread_mutex_destroy(progress->mutex) != 0) { dmnsn_error(DMNSN_SEVERITY_LOW, "Leaking mutex."); } - if (pthread_cond_destroy(&progress->cond) != 0) { + if (pthread_cond_destroy(progress->cond) != 0) { dmnsn_error(DMNSN_SEVERITY_LOW, "Leaking condition variable."); } + free(progress->mutex); + free(progress->cond); dmnsn_delete_array(progress->elements); free(progress); } @@ -68,7 +96,7 @@ int dmnsn_finish_progress(dmnsn_progress *progress) int retval = 1; if (progress) { - if (pthread_cond_broadcast(&progress->cond) != 0) { + if (pthread_cond_broadcast(progress->cond) != 0) { dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't signal condition variable."); } @@ -106,6 +134,26 @@ dmnsn_get_progress(const dmnsn_progress *progress) return prog; } +/* Wait until dmnsn_get_progress(progress) >= prog */ +void +dmnsn_wait_progress(const 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."); + } +} + /* A new level of algorithmic nesting */ void dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total) @@ -134,7 +182,7 @@ dmnsn_increment_progress(dmnsn_progress *progress) ++element->progress; } - if (pthread_cond_broadcast(&progress->cond) != 0) { + if (pthread_cond_broadcast(progress->cond) != 0) { dmnsn_error(DMNSN_SEVERITY_MEDIUM, "Couldn't signal condition variable."); } dmnsn_array_unlock(progress->elements); @@ -151,28 +199,8 @@ dmnsn_progress_done(dmnsn_progress *progress) element = dmnsn_array_at(progress->elements, 0); element->progress = element->total; - if (pthread_cond_broadcast(&progress->cond) != 0) { + 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."); - } -} |