summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libdimension/dimension/progress.h9
-rw-r--r--libdimension/progress.c88
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.");
- }
-}