summaryrefslogtreecommitdiffstats
path: root/libdimension/progress.c
diff options
context:
space:
mode:
authorTavian Barnes <tavianator@gmail.com>2009-06-23 04:26:12 +0000
committerTavian Barnes <tavianator@gmail.com>2009-06-23 04:26:12 +0000
commit02d9554b1d81e1ddae04194c299b354c04b0c706 (patch)
tree073ad103b6ac71f5ec852774dae34a5b7c03592a /libdimension/progress.c
parentefe600537740bb572f4a062ab6b9df12623e0c24 (diff)
downloaddimension-02d9554b1d81e1ddae04194c299b354c04b0c706.tar.xz
New dmnsn_array_size() thread-safe function.
Diffstat (limited to 'libdimension/progress.c')
-rw-r--r--libdimension/progress.c37
1 files changed, 23 insertions, 14 deletions
diff --git a/libdimension/progress.c b/libdimension/progress.c
index aa6891c..dc0339c 100644
--- a/libdimension/progress.c
+++ b/libdimension/progress.c
@@ -22,6 +22,7 @@
#include <pthread.h>
#include <stdlib.h> /* For malloc */
+/* Allocate a new dmnsn_progress*, returning NULL on failure */
dmnsn_progress *
dmnsn_new_progress()
{
@@ -42,6 +43,8 @@ dmnsn_new_progress()
return progress;
}
+/* Delete a dmnsn_progress*, which has not yet been associated with a thread;
+ mostly for failed returns from *_async() functions. */
void
dmnsn_delete_progress(dmnsn_progress *progress)
{
@@ -58,6 +61,7 @@ dmnsn_delete_progress(dmnsn_progress *progress)
}
}
+/* Join the worker thread and delete `progress'. */
int dmnsn_finish_progress(dmnsn_progress *progress)
{
void *ptr;
@@ -82,25 +86,27 @@ int dmnsn_finish_progress(dmnsn_progress *progress)
return retval;
}
+/* Get the current progress of the worker thread, in [0.0, 1.0] */
double
dmnsn_get_progress(const dmnsn_progress *progress)
{
dmnsn_progress_element *element;
double prog = 0.0;
- unsigned int i;
+ unsigned int i, size;
dmnsn_array_rdlock(progress->elements);
- for (i = 0; i < progress->elements->length; ++i) {
- element = dmnsn_array_at(progress->elements,
- progress->elements->length - i - 1);
- prog += element->progress;
- prog /= element->total;
- }
+ size = dmnsn_array_size_unlocked(progress->elements);
+ for (i = 0; i < size; ++i) {
+ element = dmnsn_array_at(progress->elements, size - i - 1);
+ prog += element->progress;
+ prog /= element->total;
+ }
dmnsn_array_unlock(progress->elements);
return prog;
}
+/* A new level of algorithmic nesting */
void
dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total)
{
@@ -108,20 +114,23 @@ dmnsn_new_progress_element(dmnsn_progress *progress, unsigned int total)
dmnsn_array_push(progress->elements, &element);
}
+/* Only the innermost loop needs to call this function - it handles the rest
+ upon loop completion (progress == total) */
void
dmnsn_increment_progress(dmnsn_progress *progress)
{
dmnsn_progress_element *element;
+ size_t size;
dmnsn_array_wrlock(progress->elements);
- element = dmnsn_array_at(progress->elements, progress->elements->length - 1);
+ size = dmnsn_array_size_unlocked(progress->elements);
+ element = dmnsn_array_at(progress->elements, size - 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);
+ while (element->progress >= element->total && size > 1) {
+ --size;
+ dmnsn_array_resize_unlocked(progress->elements, size);
+ element = dmnsn_array_at(progress->elements, size - 1);
++element->progress;
}
@@ -139,7 +148,7 @@ dmnsn_progress_done(dmnsn_progress *progress)
dmnsn_array_wrlock(progress->elements);
dmnsn_array_resize_unlocked(progress->elements, 1);
- element = dmnsn_array_at(progress->elements, progress->elements->length - 1);
+ element = dmnsn_array_at(progress->elements, 0);
element->progress = element->total;
if (pthread_cond_broadcast(&progress->cond) != 0) {